import pymysql
import sqlite3
import threading
import os
import json
from myutils . ConfigManager import myCongif
from myutils . MyLogger_logger import LogHandler
from myutils . MyTime import get_local_timestr
from datetime import timedelta
from datetime import datetime , timedelta
class DBManager :
#实例化数据库管理对象,并连接数据库
#itype=0 使用mysql数据库,1-使用sqlite数据库
def __init__ ( self ) :
self . logger = LogHandler ( ) . get_logger ( " DBManager " )
self . lock = threading . Lock ( )
self . itype = myCongif . get_data ( " DBType " )
self . COLUMN_LIMITS = { } #各个表字段长度信息
self . ok = False
if self . itype == 0 :
self . host = myCongif . get_data ( ' mysql.host ' )
self . port = myCongif . get_data ( ' mysql.port ' )
self . user = myCongif . get_data ( ' mysql.user ' )
self . passwd = myCongif . get_data ( ' mysql.passwd ' )
self . database = myCongif . get_data ( ' mysql.database ' )
self . connection = None
elif self . itype == 1 :
self . dbfile = myCongif . get_data ( " sqlite " )
if not os . path . exists ( self . dbfile ) :
self . dbfile = " ../ " + self . dbfile #直接运行DBManager时初始路径不是在根目录
if not os . path . exists ( self . dbfile ) :
raise FileNotFoundError ( f " Database file { self . dbfile } does not exist. " )
else :
self . logger . error ( " 错误的数据库类型,请检查 " )
def __del__ ( self ) :
if self . ok :
self . connection . close ( )
self . connection = None
self . logger . debug ( " DBManager销毁 " )
def get_column_limits ( self ) :
''' 连接成功后,统一读取数据库字段列长度设定 '''
tables = [ ' assets_user ' , ' ip_assets ' , ' ip_to_url ' , ' port_assets ' , ' task ' , ' task_llm ' , ' task_result ' , ' task_vul ' , ' url_assets ' , ' user ' , ' zf_system ' ]
for table in tables :
table_limit = { }
strsql = f '''
SELECT COLUMN_NAME , CHARACTER_MAXIMUM_LENGTH
FROM information_schema . columns
WHERE table_schema = ' your_db '
AND table_name = ' {table} ' ;
'''
datas = self . do_select ( strsql )
for data in datas :
if data [ 1 ] :
table_limit [ f " { str ( data [ 0 ] ) } " ] = data [ 1 ]
self . COLUMN_LIMITS [ f " { table } " ] = table_limit
def trim_fields ( self , table : str , data : dict , logger ) - > dict :
"""
按 COLUMN_LIMITS 截断过长的 varchar / text 字段 。
: param table : 表名
: param data : 待插入 / 更新的字段 dict
: return : 新 dict ( 已截断 )
"""
limits = self . COLUMN_LIMITS . get ( table , { } )
trimmed = { }
for col , val in data . items ( ) :
if val is None or col not in limits :
trimmed [ col ] = val
continue
max_len = limits [ col ]
# 只处理 str 类型
if isinstance ( val , str ) and len ( val ) > max_len :
self . logger . debug (
f " { table } . { col } 超长: { len ( val ) } > { max_len } ,已截断 "
)
trimmed [ col ] = val [ : max_len ]
else :
trimmed [ col ] = val
return trimmed
def connect ( self ) :
try :
if self . itype == 0 :
self . connection = pymysql . connect ( host = self . host , port = self . port , user = self . user ,
passwd = self . passwd , db = self . database , charset = ' utf8 ' )
elif self . itype == 1 :
self . connection = sqlite3 . connect ( self . dbfile )
self . ok = True
self . logger . debug ( " 服务器端数据库连接成功 " )
#self.get_column_limits()
return True
except :
self . logger . error ( " 服务器端数据库连接失败 " )
return False
# 判断数据库连接是否正常,若不正常则重连接
def Retest_conn ( self ) :
if self . itype == 0 : #除了mysql,sqlite3不需要判断连接状态
try :
self . connection . ping ( )
except :
return self . connect ( )
return True
# 执行数据库查询操作 1-只查询一条记录,其他所有记录
def do_select ( self , strsql , itype = 0 ) :
# self.conn.begin()
self . lock . acquire ( )
data = None
if self . Retest_conn ( ) :
try :
self . connection . commit ( ) # select要commit提交事务,是存在获取不到最新数据的问题(innoDB事务机制)
with self . connection . cursor ( ) as cursor :
cursor . execute ( strsql )
if itype == 1 :
data = cursor . fetchone ( )
else :
data = cursor . fetchall ( )
except Exception as e :
self . logger . error ( " do_select异常报错: %s " % str ( e ) )
self . lock . release ( )
return None
self . lock . release ( )
return data
# 执行数据库语句
def do_sql ( self , strsql , data = None ) :
bok = False
self . lock . acquire ( )
if self . Retest_conn ( ) :
try :
with self . connection . cursor ( ) as cursor :
# self.conn.begin()
if data :
iret = cursor . executemany ( strsql , data ) #批量执行sql语句
else :
iret = cursor . execute ( strsql )
self . connection . commit ( )
bok = True
except Exception as e :
self . logger . error ( " 执行数据库语句 %s 出错: %s " % ( strsql , str ( e ) ) )
self . connection . rollback ( )
self . lock . release ( )
return bok
def safe_do_sql ( self , strsql , params , itype = 0 , table = None , field_names = None ) :
"""
table : 目标表名 ( 若要自动截断必须填 )
field_names : 与 params 顺序对应的列名列表
"""
if table and field_names :
data_map = dict ( zip ( field_names , params ) )
data_map = self . trim_fields ( table , data_map , self . logger )
params = tuple ( data_map [ col ] for col in field_names )
bok = False
do_id = 0
self . lock . acquire ( )
if self . Retest_conn ( ) :
try :
with self . connection . cursor ( ) as cursor :
cursor . execute ( strsql , params )
self . connection . commit ( )
if itype == 1 : #取insert 的自增id
do_id = cursor . lastrowid
elif itype == 2 : #取删除的id,需要添加RETURNING id;
row = cursor . fetchone ( )
if row :
do_id = row [ 0 ]
bok = True
except Exception as e :
self . logger . error ( " 执行数据库语句 %s 出错: %s " % ( strsql , str ( e ) ) )
self . connection . rollback ( )
self . lock . release ( )
return bok , do_id
def safe_do_select ( self , strsql , params , itype = 0 ) :
results = [ ]
self . lock . acquire ( )
if self . Retest_conn ( ) :
self . connection . commit ( )
try :
with self . connection . cursor ( ) as cursor :
cursor . execute ( strsql , params ) # 执行参数化查询
if itype == 0 :
results = cursor . fetchall ( ) # 获取所有结果
elif itype == 1 :
results = cursor . fetchone ( ) #获得一条记录
except Exception as e :
print ( f " 查询出错: { e } -- \n { strsql } " )
self . lock . release ( )
return results
def is_json ( self , s : str ) - > bool :
if not isinstance ( s , str ) :
return False
try :
json . loads ( s )
return True
except json . JSONDecodeError :
return False
except Exception :
return False # 处理其他意外异常(如输入 None)
def timedelta_to_str ( delta : timedelta ) - > str :
hours , remainder = divmod ( delta . total_seconds ( ) , 3600 )
minutes , seconds = divmod ( remainder , 60 )
return f " { int ( hours ) : 02 } : { int ( minutes ) : 02 } : { int ( seconds ) : 02 } "
#---------------------特定数据库操作函数---------------------
def get_system_info ( self ) :
strsql = " select * from zf_system; "
data = self . do_select ( strsql , 1 )
return data
def get_run_tasks ( self ) :
strsql = " select ID,task_target,task_status,work_type,cookie_info,llm_type,safe_rank,fake_target,target_id from task where task_status <> 2 order by ID; "
datas = self . do_select ( strsql )
return datas
def start_task ( self , test_target , cookie_info , work_type , llm_type , fake_target , target_id = 0 ) - > int :
'''
数据库添加检测任务
: param task_name :
: param task_target :
: return : task_id
'''
task_id = 0
start_time = get_local_timestr ( )
sql = " INSERT INTO task (task_name,task_target,start_time,task_status,safe_rank,work_type,cookie_info,llm_type,fake_target,target_id) " \
" VALUES ( %s , %s , %s , %s , %s , %s , %s , %s , %s , %s ) "
params = ( test_target , test_target , start_time , 1 , 0 , work_type , cookie_info , llm_type , fake_target , target_id )
bok , task_id = self . safe_do_sql ( sql , params , 1 )
return task_id
def over_task ( self , task_id ) :
over_time = get_local_timestr ( )
strsql = " update task set task_status=2,end_time= %s where ID= %s ; "
params = ( over_time , task_id )
bok , _ = self . safe_do_sql ( strsql , params )
return bok
#0<-->1
def update_task_status ( self , task_id , new_status ) :
strsql = " update task set task_status= %s where ID= %s ; "
params = ( new_status , task_id )
bok , _ = self . safe_do_sql ( strsql , params )
return bok
def update_task_work_type ( self , task_id , new_work_type ) :
strsql = " update task set work_type= %s where ID= %s ; "
params = ( new_work_type , task_id )
bok , _ = self . safe_do_sql ( strsql , params )
return bok
def del_task ( self , task_id ) :
params = ( task_id )
strsql = " delete from task where ID= %s ; "
bok , _ = self . safe_do_sql ( strsql , params )
strsql = " delete from task_llm where task_id= %s ; "
bok , _ = self . safe_do_sql ( strsql , params )
strsql = " delete from task_result where task_id= %s ; "
bok , _ = self . safe_do_sql ( strsql , params )
strsql = " delete from task_vul where task_id= %s ; "
bok , _ = self . safe_do_sql ( strsql , params )
return bok
#指令执行结果入库
def insetr_result ( self , task_id , instruction , result , do_sn , start_time , end_time , source_result , ext_params , node_path ) :
str_result = " "
str_source_result = " "
# 统一将 result 转为 JSON 字符串(无论原始类型)
try :
if not isinstance ( result , str ) :
str_result = json . dumps ( result , ensure_ascii = False )
else :
# 如果是字符串,先验证是否为合法 JSON(可选)
json . loads ( result )
str_result = result
except ( TypeError , json . JSONDecodeError ) :
str_result = json . dumps ( str ( result ) , ensure_ascii = False ) # 兜底处理非 JSON 字符串
try :
if not isinstance ( source_result , str ) :
str_source_result = json . dumps ( source_result , ensure_ascii = False )
else :
# 如果是字符串,先验证是否为合法 JSON(可选)
json . loads ( source_result )
str_source_result = source_result
except ( TypeError , json . JSONDecodeError ) :
str_source_result = json . dumps ( str ( source_result ) , ensure_ascii = False ) # 兜底处理非 JSON 字符串
# 使用参数化查询
sql = """
INSERT INTO task_result
( task_id , instruction , result , do_sn , start_time , end_time , source_result , is_user , is_vulnerability , node_path )
VALUES
( % s , % s , % s , % s , % s , % s , % s , % s , % s , % s )
"""
params = ( task_id , instruction , str_result , do_sn , start_time , end_time , source_result , ext_params [ ' is_user ' ] ,
ext_params [ ' is_vulnerability ' ] , node_path )
bok , _ = self . safe_do_sql ( sql , params )
return bok
#llm数据入库
def insert_llm ( self , task_id , prompt , reasoning_content , content , post_time , llm_sn , path ) :
str_reasoning = " "
str_content = " "
try :
if not isinstance ( reasoning_content , str ) :
str_reasoning = json . dumps ( reasoning_content ) #,ensure_ascii=False
else :
# 如果是字符串,先验证是否为合法 JSON(可选)
json . loads ( reasoning_content )
str_reasoning = reasoning_content
except ( TypeError , json . JSONDecodeError ) :
str_reasoning = json . dumps ( str ( reasoning_content ) ) # 兜底处理非 JSON 字符串
try :
if not isinstance ( content , str ) :
str_content = json . dumps ( content )
else :
# 如果是字符串,先验证是否为合法 JSON(可选)
json . loads ( content )
str_content = content
except ( TypeError , json . JSONDecodeError ) :
str_content = json . dumps ( str ( content ) ) # 兜底处理非 JSON 字符串
sql = """
INSERT INTO task_llm
( task_id , do_sn , prompt , reasoning_content , content , start_time , node_path )
VALUES
( % s , % s , % s , % s , % s , % s , % s )
"""
str_reasoning = str_reasoning . encode ( ' utf-8 ' ) . decode ( ' unicode_escape ' )
str_content = str_content . encode ( ' utf-8 ' ) . decode ( ' unicode_escape ' )
params = ( task_id , llm_sn , prompt , str_reasoning , str_content , post_time , path )
bok , _ = self . safe_do_sql ( sql , params )
return bok
#获取任务的测试指令执行情况
def get_task_instrs ( self , task_id , nodename ) :
strsql = '''
select ID , node_path , do_sn , instruction , result from task_result where task_id = % s
'''
params = [ task_id ]
if nodename . strip ( ) :
strsql + = " and node_path like %s "
params . append ( f " % { nodename } % " ) # 在参数中添加通配符
datas = self . safe_do_select ( strsql , tuple ( params ) )
return datas
#插入漏洞数据
def insert_taks_vul ( self , task_id , node_name , node_path , vul_type , vul_level , vul_info ) :
strsql = '''
INSERT INTO task_vul
( task_id , node_name , node_path , vul_type , vul_level , vul_info )
VALUES ( % s , % s , % s , % s , % s , % s )
'''
params = ( task_id , node_name , node_path , vul_type , vul_level , vul_info )
bok , _ = self . safe_do_sql ( strsql , params )
return bok
#获取任务的漏洞检测情况
def get_task_vul ( self , task_id , nodename , vultype , vullevel ) :
strsql = '''
select ID , node_path , vul_type , vul_level , vul_info from task_vul
'''
# 动态构建查询条件
conditions = [ " task_id= %s " ] # task_id 必须存在
params = [ task_id ] # 参数列表初始化
# 按需添加其他条件
if nodename and nodename . strip ( ) : # 检查nodename是否非空(去除前后空格后)
conditions . append ( " node_path like %s " )
params . append ( f " % { nodename } % " )
if vultype and vultype . strip ( ) : # 检查vultype是否非空
conditions . append ( " vul_type like %s " )
params . append ( f " % { vultype } % " )
if vullevel and vullevel . strip ( ) : # 检查vullevel是否非空
conditions . append ( " vul_level= %s " )
params . append ( vullevel )
# 组合完整的WHERE子句
if len ( conditions ) > 0 :
strsql + = " WHERE " + " AND " . join ( conditions )
# 执行查询(将参数转为元组)
datas = self . safe_do_select ( strsql , tuple ( params ) )
return datas
#获取该任务该节点的所有 已经执行的任务
def get_task_node_done_instr ( self , task_id , nodepath ) :
strsql = '''
select instruction , start_time , result from task_result where task_id = % s and node_path = % s order by start_time desc ;
'''
params = ( task_id , nodepath )
datas = self . safe_do_select ( strsql , params )
return datas
def get_his_tasks ( self , target_name , safe_rank , llm_type , start_time , end_time ) :
strsql = " select ID,task_target,safe_rank,llm_type,start_time,end_time from task "
conditions = [ " task_status= %s " ]
params = [ 2 ]
# 按需添加其他条件
if target_name and target_name . strip ( ) : # 检查nodename是否非空(去除前后空格后)
conditions . append ( " task_target= %s " )
params . append ( target_name )
if safe_rank and safe_rank . strip ( ) : # 检查vultype是否非空
conditions . append ( " safe_rank= %s " )
params . append ( safe_rank )
if llm_type and llm_type . strip ( ) : # 检查vullevel是否非空
conditions . append ( " llm_type= %s " )
params . append ( llm_type )
if start_time and start_time . strip ( ) : # 检查vultype是否非空
conditions . append ( " start_time >= %s " )
start_date = datetime . strptime ( start_time , " % Y- % m- %d " )
# 生成起始时间字符串(当日 00:00:00)
start_time_str = start_date . strftime ( " % Y- % m- %d 00:00:00 " )
params . append ( start_time_str )
if end_time and end_time . strip ( ) : # 检查vullevel是否非空
conditions . append ( " start_time < %s " )
# 将输入字符串转为日期对象
end_date = datetime . strptime ( end_time , " % Y- % m- %d " )
# 生成结束时间字符串(次日 00:00:00)
end_time_str = ( end_date + timedelta ( days = 1 ) ) . strftime ( " % Y- % m- %d 00:00:00 " )
params . append ( end_time_str )
# 组合完整的WHERE子句
if len ( conditions ) > 0 :
strsql + = " WHERE " + " AND " . join ( conditions )
strsql + = " order by start_time DESC "
# 执行查询(将参数转为元组)
datas = self . safe_do_select ( strsql , tuple ( params ) )
return datas
def getsystem_info ( self ) :
strsql = " select local_ip,version from zf_system; "
data = self . do_select ( strsql , 1 )
return data
def update_localip ( self , local_ip ) :
strsql = " update zf_system set local_ip= %s ; "
params = ( local_ip )
bok , _ = self . safe_do_sql ( strsql , params )
return bok
def get_one_instr ( self , instr_id ) :
strsql = " select instruction from task_result where ID = %s "
params = ( instr_id )
data = self . safe_do_select ( strsql , params , 1 )
return data [ 0 ]
#------------------资产表相关----------------------
def add_or_update_URL_asset ( self , Domain , Subdomains , Registrant , Email , Creation_date , Expiration_date , Registrar ) :
strsql = " select ID from url_assets where URL= %s "
params = ( Domain )
data = self . safe_do_select ( strsql , params , 1 )
do_time = get_local_timestr ( )
if Subdomains :
strSubdomains = ' , ' . join ( Subdomains )
else :
strSubdomains = " "
if not data : #没有数据则新增
strsql = " insert into url_assets (registrar,creation_date,expiration_date,emails,create_time,update_time,URL,subdomains,Registrant) " \
" values ( %s , %s , %s , %s , %s , %s , %s , %s , %s ) "
params = ( Registrar , Creation_date , Expiration_date , Email , do_time , do_time , Domain , strSubdomains , Registrant )
bok , url_id = self . safe_do_sql ( strsql , params , 1 )
else : #有值则修改
url_id = data [ 0 ]
strsql = " update url_assets set registrar= %s ,Registrant= %s ,creation_date= %s ,expiration_date= %s ,emails= %s ,update_time= %s , " \
" subdomains= %s where ID = %s ; "
params = ( Registrar , Registrant , Creation_date , Expiration_date , Email , do_time , strSubdomains , url_id )
bok , _ = self . safe_do_sql ( strsql , params )
#维护历史记录 --由数据库触发器维护
return url_id
def add_or_update_IP_asset ( self , IP , ip_type ) :
#return ip_id scan_count
strsql = " select id,scan_count from ip_assets where ip_address = %s ; "
params = ( IP )
data = self . safe_do_select ( strsql , params , 1 )
if data :
return data [ 0 ] , data [ 1 ]
#IP没有则新建入库
ip_id = 0
start_time = get_local_timestr ( )
sql = " INSERT INTO ip_assets (ip_address,ip_version,created_time,scan_count) VALUES ( %s , %s , %s , %s ); "
params = ( IP , ip_type , start_time , 0 )
bok , ip_id = self . safe_do_sql ( sql , params , 1 )
return ip_id , 0
#将task_id 和ip资产进行关联
def add_task_to_ip ( self , task_id , ip_id ) :
strsql = " INSERT INTO task_to_ip (task_id,ip_id) VALUES ( %s , %s ); "
params = ( task_id , ip_id )
bok , _ = self . safe_do_sql ( strsql , params )
return bok
def update_port ( self , ip_id , scan_count , Prots ) :
update_time = get_local_timestr ( )
scan_count + = 1
strsql = " update ip_assets set update_time = %s ,scan_count = %s where id= %s "
params = ( update_time , scan_count , ip_id )
bok , _ = self . safe_do_sql ( strsql , params )
if bok :
#最新的port数据入库 {\"Protocol\":\"TCP/UDP\",\"Status\":\"open/closed/filtered\"};
for port in Prots :
p_num = port [ " Port " ]
service = port [ " Service " ]
version = port [ " Version " ]
protocol = port [ " Protocol " ]
status = port [ " Status " ]
strsql = " insert into port_assets (port,service,version,status,ip_id,scan_count,scan_time,Protocol) " \
" values ( %s , %s , %s , %s , %s , %s , %s , %s ) "
params = ( p_num , service , version , status , ip_id , scan_count , update_time , protocol )
bok , _ = self . safe_do_sql ( strsql , params )
return bok
def update_url_to_ip ( self , url_id , ips ) :
strsql = " select ip_id from ip_to_url where url_id = %s "
params = ( url_id )
datas = self . safe_do_select ( strsql , params )
old_ips = [ ]
for data in datas :
old_ips . append ( data [ 0 ] )
only_in_old = list ( set ( old_ips ) - set ( ips ) ) #适合不重复,不关心顺序的情况
only_in_new = list ( set ( ips ) - set ( old_ips ) )
do_time = get_local_timestr ( )
if only_in_old : #新的关联中没有,老的有,就是删除了
placeholders = " , " . join ( [ " ( %s , %s , %s ) " ] * len ( only_in_old ) )
sql = f """
INSERT INTO ip_to_url_his ( ip_id , url_id , del_time )
VALUES { placeholders }
"""
# 扁平化参数列表
params : list = [ ]
for ip in only_in_old :
params + = [ ip , url_id , do_time ]
# 一次性执行
bok , _ = self . safe_do_sql ( sql , tuple ( params ) )
if not bok :
raise RuntimeError ( " 批量插入 ip_to_url_his 失败 " )
#老表中删除记录---待验证
strsql = '''
delete from ip_to_url where url_id = % s and ip_id in ( % s )
'''
del_ips = ' , ' . join ( [ str ( x ) for x in only_in_old ] )
params = ( url_id , del_ips )
bok , _ = self . safe_do_sql ( strsql , params )
if not bok :
raise RuntimeError ( " 批量删除 ip_to_url 失败 " )
if only_in_new : #新的有,老的没有就是新增。
placeholders = " , " . join ( [ " ( %s , %s , %s ) " ] * len ( only_in_new ) )
sql = f """
INSERT INTO ip_to_url ( ip_id , url_id , create_time )
VALUES { placeholders }
"""
# 扁平化参数列表
params : list = [ ]
for ip in only_in_new :
params + = [ ip , url_id , do_time ]
# 一次性执行
bok , _ = self . safe_do_sql ( sql , tuple ( params ) )
if not bok :
raise RuntimeError ( " 批量插入 ip_to_url 失败 " )
def get_ip_assets_db ( self , IP , user , risk_rank ) :
strsql = '''
SELECT
ia . ip_address ,
au . uname ,
ia . risk_rank ,
ia . update_time ,
COALESCE ( p . port_cnt , 0 ) AS port_total ,
COALESCE ( u . url_cnt , 0 ) AS url_total
FROM ip_assets AS ia
LEFT JOIN assets_user AS au ON ia . owner_id = au . ID
/ * 端口数量 * /
LEFT JOIN (
SELECT ip_id , scan_count , COUNT ( * ) AS port_cnt
FROM port_assets
GROUP BY ip_id , scan_count
) AS p ON p . ip_id = ia . id and p . scan_count = ia . scan_count
/ * URL 数量 * /
LEFT JOIN (
SELECT ip_id , COUNT ( * ) AS url_cnt
FROM ip_to_url
GROUP BY ip_id
) AS u ON u . ip_id = ia . id
WHERE
( % s IS NULL OR ia . ip_address LIKE % s )
AND ( % s IS NULL OR au . uname LIKE % s )
AND ( % s IS NULL OR ia . risk_rank = % s ) ;
'''
# 构造参数
ip_like = f " % { IP } % " if IP else None
user_like = f " % { user } % " if user else None
rk = risk_rank
params = (
ip_like , ip_like ,
user_like , user_like ,
rk , rk ,
)
# cursor.execute(sql, params)
# rows = cursor.fetchall()
datas = self . safe_do_select ( strsql , params )
return datas
def get_ip_info_db ( self , IP ) :
strsql = '''
select au . ID , au . tellnum , au . tell_username from assets_user as au
left join ip_assets as ai on ai . owner_id = au . ID
where ai . ip_address = % s ;
'''
params = ( IP )
data = self . safe_do_select ( strsql , params , 1 )
return data
def get_assets_users_db ( self , uname ) :
if uname :
strsql = " select ID,uname,tellnum,tell_username from assets_user where uname like %s ; "
params = ( f ' % { uname } % ' )
datas = self . safe_do_select ( strsql , params )
else :
strsql = " select ID,uname,tellnum,tell_username from assets_user; "
datas = self . do_select ( strsql )
return datas
def update_assets_users_db ( self , IP , owner_id , itype ) :
if itype == 1 :
strsql = '''
update ip_assets set owner_id = % s where ip_address = % s ;
'''
else :
strsql = '''
update url_assets set owner_id = % s where ID = % s ;
'''
params = ( owner_id , IP )
bok , _ = self . safe_do_sql ( strsql , params )
error = " "
if not bok :
error = " 修改资产所属用户失败 "
return bok , error
def get_port_latest_db ( self , ip ) :
strsql = '''
select po . port , po . service , po . version , po . status from port_assets as po
left join ip_assets as ip
on ip . id = po . ip_id and ip . scan_count = po . scan_count
where ip . ip_address = % s
'''
params = ( ip )
datas = self . safe_do_select ( strsql , params )
return datas
def get_ip_url_latest_db ( self , ip ) :
strsql = '''
select url . URL , url . subdomains , url . registrar , url . emails , url . creation_date , url . expiration_date from url_assets as url
left join ip_to_url as i2u on i2u . url_id = url . ID
left join ip_assets as ip on ip . id = i2u . ip_id
where ip_address = % s ;
'''
params = ( ip )
datas = self . safe_do_select ( strsql , params )
return datas
def get_ip_url_history_db ( self , ip ) :
#先把ip_id获取到
strsql = " select id from ip_assets where ip_address= %s ; "
params = ( ip , )
data = self . safe_do_select ( strsql , params , 1 )
if not data :
return None
ip_id = data [ 0 ]
strsql = '''
select url . URL , i2u . create_time as time , ' add ' as type from ip_to_url as i2u
left join url_assets as url on url . ID = i2u . url_id
where ip_id = % s
union all
select url . URL , i2u_his . del_time as time , ' del ' as type from ip_to_url_his as i2u_his
left join url_assets as url on url . ID = i2u_his . url_id
where ip_id = % s
order by time DESC ;
'''
params = ( ip_id , ip_id )
datas = self . safe_do_select ( strsql , params )
return datas
def del_url_assets_db ( self , url_id ) :
#url assets
strsql = " delete from url_assets where ID= %s ; "
params = ( url_id , )
bok , _ = self . safe_do_sql ( strsql , params )
#url_assets_his
strsql = " delete from url_assets_his where url_id= %s ; "
bok , _ = self . safe_do_sql ( strsql , params )
#ip_to_url
strsql = " delete from ip_to_url where url_id = %s ; "
bok , _ = self . safe_do_sql ( strsql , params )
#ip_to_url_his
strsql = " delete from ip_to_url_his where url_id = %s ; "
bok , _ = self . safe_do_sql ( strsql , params )
return True , " 删除URL资产成功 "
def get_last_task_by_ip ( self , ip ) :
#寻找该IP最新完成的任务
strsql = '''
SELECT t . ID AS latest_task_id , t . start_time
FROM ip_assets AS ia
JOIN task_to_ip AS ti ON ia . id = ti . ip_id
JOIN task AS t ON ti . task_id = t . ID
WHERE ia . ip_address = % s
ORDER BY t . start_time DESC
LIMIT 1 ;
'''
params = ( ip , )
data = self . safe_do_select ( strsql , params , 1 )
if data :
return data [ 0 ]
else :
return None
def del_ip_assets ( self , ip ) :
#删除IP资产 -- 资产库中跟该资产相关的数据都需要删除,return bok,error
bok = False
# ip_assets
sql = """
DELETE FROM ip_assets
WHERE ip_address = % s
RETURNING id ;
"""
params = ( ip , )
bok , ip_id = self . safe_do_sql ( sql , params , 2 )
if ip_id :
#task_to_ip
strsql = " delete from task_to_ip where ip_id = %s ; "
bok , _ = self . safe_do_sql ( strsql , params )
#ip_to_url
strsql = " delete from ip_to_url where ip_id = %s ; "
bok , _ = self . safe_do_sql ( strsql , params )
#ip_to_url_his
strsql = " delete from ip_to_url_his where ip_id = %s ; "
bok , _ = self . safe_do_sql ( strsql , params )
#port_assets
strsql = " delete from port_assets where ip_id = %s ; "
bok , _ = self . safe_do_sql ( strsql , params )
return True , " 删除成功 "
def get_url_assets_db ( self , url , owner , email ) :
url_assets = [ ]
strsql = '''
select url . ID , url . URL , au . uname , url . emails , url . update_time , url . expiration_date , ip . ip_count , url . Registrant , au . tellnum , au . tell_username , au . ID from url_assets as url
left join assets_user as au on au . ID = url . owner_id
left join ( select url_id , count ( * ) as ip_count from ip_to_url group by url_id ) as ip on url . ID = ip . url_id
'''
conditions = [ ]
params = [ ]
if url and url . strip ( ) :
conditions . append ( " url.URL like %s " )
params . append ( f " % { url } % " )
if owner and owner . strip ( ) :
conditions . append ( " au.uname like %s " )
params . append ( f " % { owner } % " )
if email and email . strip ( ) :
conditions . append ( " url.emails like %s " )
params . append ( f " % { email } % " )
if len ( conditions ) > 0 :
strsql + = " WHERE " + " AND " . join ( conditions )
# 执行查询(将参数转为元组)
url_assets = self . safe_do_select ( strsql , tuple ( params ) )
return url_assets
def get_url_to_ip_db ( self , url_id ) :
strsql = '''
select ia . ip_address , itu . create_time from ip_assets ia
left join ip_to_url itu on itu . ip_id = ia . id
where itu . url_id = % s ;
'''
params = ( url_id , )
last_to_ips = self . safe_do_select ( strsql , params )
strsql = '''
select ia . ip_address , itu . del_time from ip_assets ia
left join ip_to_url_his itu on itu . ip_id = ia . id
where itu . url_id = % s ;
'''
params = ( url_id , )
his_to_ips = self . safe_do_select ( strsql , params )
return last_to_ips , his_to_ips
def get_owner_db ( self , owner , owner_type , contact , tellnum ) :
strsql = '''
SELECT
u . ID ,
u . itype ,
u . uname ,
u . tellnum ,
u . tell_username ,
u . ID_num ,
IFNULL ( ip . ip_count , 0 ) AS ip_count ,
IFNULL ( url . url_count , 0 ) AS url_count ,
IFNULL ( ip . ip_count , 0 ) + IFNULL ( url . url_count , 0 ) AS total_assets
FROM assets_user u
LEFT JOIN (
SELECT owner_id , COUNT ( * ) AS ip_count
FROM ip_assets
GROUP BY owner_id
) ip ON u . ID = ip . owner_id
LEFT JOIN (
SELECT owner_id , COUNT ( * ) AS url_count
FROM url_assets
GROUP BY owner_id
) url ON u . ID = url . owner_id
'''
conditions = [ ]
params = [ ]
# 按需添加其他条件
if owner and owner . strip ( ) :
conditions . append ( " uname like %s " )
params . append ( f " % { owner } % " )
if owner_type and owner_type . strip ( ) :
conditions . append ( " itype= %s " )
params . append ( owner_type )
if contact and contact . strip ( ) :
conditions . append ( " tell_username like %s " )
params . append ( f " % { contact } % " )
if tellnum and tellnum . strip ( ) :
conditions . append ( " tellnum like %s " )
params . append ( f " % { tellnum } % " )
# 组合完整的WHERE子句
if len ( conditions ) > 0 :
strsql + = " WHERE " + " AND " . join ( conditions )
# 执行查询(将参数转为元组)
datas = self . safe_do_select ( strsql , tuple ( params ) )
return datas
def del_owner_db ( self , id ) :
strsql = " delete from assets_user where ID= %s ; "
params = ( id , )
bok , _ = self . safe_do_sql ( strsql , params )
#删除IP和URL与owner的关系
strsql = " update ip_assets set owner_id = 0 where owner_id = %s ; "
bok , _ = self . safe_do_sql ( strsql , params )
strsql = " update url_assets set owner_id = 0 where owner_id = %s ; "
bok , _ = self . safe_do_sql ( strsql , params )
return True , " "
def get_polling_target_db ( self , PT , owner , PP , safe_rank ) :
strsql = '''
select t . scr_target , o . uname , t . polling_period , t . polling_last_time , t . risk_rank , t . polling_type , t . polling_start_time from target t
left join assets_user o on o . ID = t . owner_id
'''
conditions = [ ]
params = [ ]
# 按需添加其他条件
if PT and PT . strip ( ) :
conditions . append ( " t.scr_target like %s " )
params . append ( f " % { PT } % " )
if owner and owner . strip ( ) :
conditions . append ( " o.uname like %s " )
params . append ( f " % { owner } % " )
if PP and PP . strip ( ) :
conditions . append ( " t.polling_period= %s " )
params . append ( PP )
if safe_rank and safe_rank . strip ( ) :
conditions . append ( " t.risk_rank = %s " )
params . append ( safe_rank )
# 组合完整的WHERE子句
if len ( conditions ) > 0 :
strsql + = " WHERE " + " AND " . join ( conditions )
# 执行查询(将参数转为元组)
datas = self . safe_do_select ( strsql , tuple ( params ) )
return datas
def update_polling_last_time ( self , target_ID ) :
str_time = get_local_timestr ( )
strsql = " update target set polling_last_time = %s where ID= %s ; "
params = ( str_time , target_ID )
bok , _ = self . safe_do_sql ( strsql , params )
return bok
def test ( self ) :
# 建立数据库连接
conn = pymysql . connect (
host = ' localhost ' ,
port = 3306 ,
user = ' username ' ,
password = ' password ' ,
database = ' database_name '
)
# 创建游标对象
cursor = conn . cursor ( )
# 执行 SQL 查询
query = " SELECT * FROM table_name "
cursor . execute ( query )
# 获取查询结果
result = cursor . fetchall ( )
# 输出结果
for row in result :
print ( row )
# 关闭游标和连接
cursor . close ( )
conn . close ( )
#全局的单一实例
app_DBM = DBManager ( )
app_DBM . connect ( )
if __name__ == " __main__ " :
# mDBM = DBManager()
# mDBM.connect()
# print(mDBM.start_task("11","22"))
list_a = [ ' 1 ' , ' 2 ' , ' 3 ' , ' 4 ' , ' 5 ' , ' 6 ' ]
str_a = ' , ' . join ( list_a )
print ( str_a )