一、脚本实现思路
1)从配置文件读取数据库连接信息;
2)在脚本中自定义脱敏字段后,可以全库表扫描,敏感字段存在于哪些库表中,并结构化输出;
3)本次脱敏字段为身份证号、手机号、password和用户名称,脱敏规则为混入4位随机数字字符,脱敏方法是直接修改数据库原始数据;
4)方法一实现一条条更改数据,问题是效率低,可以改造成多线程;方法二使用的是sql语句批量更新,速度快;
5)通过调整最下面的注释开关,可以控制全量更新,还是单库表更新;
二、具体脚本实现
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import MySQLdb
import os, sys
import random
## get mysql connection config
PATH = os.getcwd()
d = {}
for F in open(PATH + "/conf.ini",'r+').readlines():
key = F.split(":")[0]
value = F.split(":")[1].strip()
d[key] = value
## connection mysql
class Mysql(object):
def __init__(self, host, user, passwd,db_name):
self.host = host
self.user = user
self.passwd = passwd
self.db_name = db_name
self.mingan_list = ["password", "mobile", "phone", "linephone", "idno", "parentidno","studentname","fathername","mothername","membername","parentname","employeename","emp_name","childname","username"]
self.mingan_name_list = ["studentname","fathername","mothername","membername","parentname","employeename","emp_name","childname","username"]
self.mingan_idno_list = ["idno", "parentidno"]
self.mingan_other_list = ["mobile", "phone", "linephone"]
def connect(self):
"""
创建数据库连接
:param database: 需要连接的数据库
:return: 数据库连接对象
"""
try:
conn = MySQLdb.connect(
host=self.host,
user=self.user,
passwd=self.passwd,
db=self.db_name,
charset='utf8')
return conn
except Exception as e:
print e
sys.exit(1)
def select(self,sql):
"""
执行sql命令
:param sql: sql语句
:return: 元组
"""
try:
conn = self.connect()
cursor = conn.cursor()
cursor.execute(sql)
res = cursor.fetchall()
cursor.close()
conn.close()
return res
except Exception as e:
print e
sys.exit(1)
def get_all_db(self):
"""
获取所有数据库名
:return: list
"""
exclude_list = ["sys", "information_schema", "mysql", "performance_schema"]
sql = "show databases"
res = self.select(sql)
if not res:
return False
db_list = []
for i in res:
db_name = i[0]
if db_name not in exclude_list:
db_list.append(db_name)
if not db_list:
return False
return db_list
def get_tables(self):
"""
获取表
:return: list
"""
sql = "show tables"
res = self.select(sql)
if not res:
print "%s none table" % (self.db_name)
sys.exit(1)
table_list = []
for i in res:
table_name = i[0]
table_list.append(table_name)
if not table_list:
return False
return table_list
def desc(self, tables_name):
"""
get table desc
:param tables_name: table
:return: list
"""
try:
conn = self.connect()
cursor = conn.cursor()
cursor.execute("select * from %s limit 1" % tables_name)
res = [tuple[0] for tuple in cursor.description]
cursor.close()
conn.close()
return res
except Exception as e:
print e
sys.exit(1)
def get_table_fields(self,table):
"""
获取表结构
:return: list
"""
include_list = self.mingan_list
res = self.desc(table)
if not res:
return False
for table_field in include_list:
if table_field in res:
return table_field
def updateSql(self,database,table,field):
def randomNum():
code = ''
for i in range(4):
num = random.randint(0,9)
code += str(num)
return code
print "updating %s's table %s's field %s" % (database,table,field)
sql = "select %s from %s where %s is not null and %s != ''" % (field,table,field,field)
conn = self.connect()
cursor = conn.cursor()
cursor.execute(sql)
exec_conn = self.connect()
exec_cursor = exec_conn.cursor()
while True:
randomCode = randomNum()
value = cursor.fetchone()
if not value:
break
else:
old_value = value[0]
print old_value
try:
if field not in self.mingan_name_list:
tempNum = old_value[0:-4]
else:
tempNum = old_value[0]
except Exception as e:
print e
continue
new_value = tempNum + randomCode
sql = "update %s set %s = '%s' where %s = '%s'" % (table,field,new_value,field,old_value)
print sql
try:
exec_cursor.execute(sql)
exec_conn.commit()
except Exception as e:
print e
sys.exit(1)
cursor.close()
conn.close()
exec_cursor.close()
exec_conn.close()
def updateSqlTwo(self,database,table,field):
print "updating %s's table %s's field %s" % (database,table,field)
if field in self.mingan_name_list:
position = 1
sql = "update %s set %s = concat(substring(%s,1,%d),CEILING(RAND()*8999+1000)) where %s is not null and %s != '' and LENGTH(%s) > %d" % (table,field,field,position,field,field,field,position)
elif field in self.mingan_idno_list:
position = 14
sql = "update %s set %s = concat(substring(%s,1,%d),CEILING(RAND()*8999+1000)) where %s is not null and %s != '' and LENGTH(%s) > %d" % (table,field,field,position,field,field,field,position)
elif field == "password":
sql = "update %s set %s = '333333' where %s is not null and %s != ''" % (table,field,field,field)
else:
position = 7
sql = "update %s set %s = concat(substring(%s,1,%d),CEILING(RAND()*8999+1000)) where %s is not null and %s != '' and LENGTH(%s) > %d" % (table,field,field,position,field,field,field,position)
print sql
conn = self.connect()
cursor = conn.cursor()
try:
cursor.execute(sql)
conn.commit()
except Exception as e:
print e
sys.exit(1)
cursor.close()
conn.close()
if __name__ == '__main__':
host = d['host']
user = d['user']
passwd = d['passwd']
database = 'mysql'
result = {}
obj = Mysql(host,user,passwd,database)
all_db_list = obj.get_all_db()
for i in all_db_list:
database = i
obj = Mysql(host,user,passwd,database)
all_table_list = obj.get_tables()
tables = []
for table in all_table_list:
field = obj.get_table_fields(table)
if field:
tables.append(table)
result[database] = tables
print "%s exist %s's %s" % (field,database,table)
# obj.updateSqlTwo(database,table,field)
# obj = Mysql(host,user,passwd,sys.argv[1])
# obj.updateSqlTwo(sys.argv[1],sys.argv[2],sys.argv[3])
# print result
配置文件格式为
host:XXX
user:XXX
passwd:XXX