各个平台、网站都有要设置对应的账号密码,太多账号密码需要记住,经常容易搞混或者忘记,需要找回密码。结合前面学到的使用Ukey对数据的加解密以及可视化Pyside2,想到用这些完成个人账号密码的管理,可以用来记录自己各个账号密码。
有关使用Ukey完成对数据的加解密可以参考python-使用U盾完成数据的加解密(使用国密算法SKF接口)
参考下方链接的登录界面实现
python-U盾数据加解密可视化_pyside2
功能:
- 加载数据:读取MyPassword.db数据库文件,并对加密部分实现解密,最后将数据显示在界面上
- 新增:新增需要管理的账号密码
- 保存:加密保存需要新增的、修改的账号密码
- 删除:删除选中的账号密码
- 修改:直接在表格中修改
界面:
涉及的控件:
- QPushButton:
- pushButton_Add:新增按键
- pushButton_Delete:删除按键
- pushButton_LoadData:加载数据按键
- pushButton_Save:保存按键
- QTableWidget:
- tableWidget:数据显示的表格控件
函数:
控件触发函数:
def load_date(self)
:加载数据def add_row(self)
:新增一行def save_date(self)
:保存def delete_date(self)
:删除def change_cell(self, row, column)
:修改表中的内容时需要触发的函数。其他函数:
def init_date(self)
:用于在加载函数中,从MyPassword.db数据库中读取数据,完成对数据的解密操作def create_table(self)
:加载数据的,,如果当前路径没有MyPassword.db数据库文件,则新建数据。def play_header(self, table_name)
:用于在加载数据时,对表格进行表头的显示设置其他:
加载操作数据库的类:
self.db = MyOperationDb(DB_NAME)
为了方便使用sqlite3库,由此封装一个自己的类,主要的功能有:
def __connect_db(self, db_name)
:连接或者创建数据库def operation(self, str_sql, commit=False)
:传入Sql语句,执行操作,默认commit=False,若执行insert,update,delete操作需要传Truedef get_query_date(self)
:执行查询操作后用于获取数据def get_all_date(self, table_name)
:获取指定表的所有数据def get_tables_name(self)
:取数据库中所有表的名def get_table_filed(self, table_name)
:传入表名,获取表的字段信息def delete_table(self, table_name)
:删除指定的表def get_table_count(self, table_name)
:获取当前数据库总共有多少张表def __del__
:关闭相关的句柄
Python-使用U盾完成数据的加解密(使用国密算法SKF接口)
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
@Project :Python_Pyside2
@File :MySqlite3.py
@IDE :PyCharm
@Author :羽丶千落
@Date :2022-11-16 21:14
@content:
"""
import sqlite3
class MyOperationDb(object):
def __init__(self, db_name):
self.db_name = db_name
self.conn = self.__connect_db(self.db_name)
self.cur = self.conn.cursor()
self.tables_name = self.get_tables_name()
# 连接或者创建数据库
def __connect_db(self, db_name):
conn = sqlite3.connect(db_name)
return conn
# 传入Sql语句,执行操作,默认commit=False,若执行insert,update,delete操作需要传True
def operation(self, str_sql, commit=False):
self.cur.execute(str_sql)
if commit is True:
self.conn.commit()
# 执行查询操作后用于获取数据
def get_query_date(self):
result = self.cur.fetchall()
return result
def get_all_date(self, table_name):
self.operation("select * from {}".format(table_name))
return self.get_query_date()
# 获取数据库中所有表的名
def get_tables_name(self):
self.operation("select name from sqlite_master where type='table' order by name")
return self.get_query_date()
# 传入表名,获取表的字段信息
def get_table_filed(self, table_name):
self.operation("pragma table_info({0})".format(table_name))
filed = self.get_query_date()
result = []
for f in filed:
result.append(f[1])
return result
def delete_table(self, table_name):
self.operation("drop table ({0})".format(table_name), commit=True)
def get_table_count(self, table_name):
self.operation("select count(*) from {0}".format(table_name))
count = self.get_query_date()
return count[0][0]
# 关闭相关的句柄
def __del__(self):
self.cur.close()
self.conn.close()
from PySide2.QtWidgets import QApplication, QTableWidgetItem
from PySide2.QtUiTools import QUiLoader
from PySide2.QtCore import Qt
from MySqlite3 import MyOperationDb
from MySkfClass import *
# 基本DB配置信息
DB_NAME = "MyPassword.db"
TABLE_NAME = "PasswordTable"
TABLE_FIELD = ["ID", "NAME", "ACCOUNT", "PASSWORD"]
# Ukey配置信息
dll_path = r"C:\WINDOWS\system32\xxxxxx.dll"
myskf = MySkfClass(dll_path)
class WinLogin(object):
def __init__(self, skf):
self.login_ui = QUiLoader().load("../UI/Login.ui") # 动态加载UI文件
self.login_ui.pushButton_Login.clicked.connect(self.click_login) # 登录按键
self.login_ui.pushButton_Exit.clicked.connect(self.click_exit) # 退出按键
self.login_ui.lineEdit_UkeyPIN.returnPressed.connect(self.enter_pressed)
self.skf = skf
def click_login(self):
self.skf.Init_handle()
if self.skf.error != 0: # 判断设备是否已经插入
self.login_ui.label_PinCount.setText("初始化Ukey错误,请确保Ukey已插入")
self.skf.close_handle()
return
input_pin = self.login_ui.lineEdit_UkeyPIN.text() # 获取PIN框的值
count_pin = self.skf.VerifyPIN(input_pin)
if self.skf.error != 0: # 判断PIN是否正确
self.login_ui.label_PinCount.setText("PIN错误,剩余{}次".format(count_pin))
self.skf.close_handle()
return
play.function_ui = MyPassword(self.skf)
self.login_ui.lineEdit_UkeyPIN.setText("")
self.login_ui.hide()
play.function_ui.password_ui.show()
self.login_ui.close()
def click_exit(self):
self.login_ui.close()
def enter_pressed(self):
return self.click_login()
class MyPassword(object):
def __init__(self, skf):
# 动态加载UI
self.password_ui = QUiLoader().load("../UI/MyPasswordUI.ui")
self.change_date = {} # 在load_date中定义
self.add_date = {}
self.add_id = []
self.skf = skf
self.db = MyOperationDb(DB_NAME)
# 按键链接函数
self.password_ui.pushButton_LoadDate.clicked.connect(self.load_date)
self.password_ui.pushButton_Add.clicked.connect(self.add_row)
self.password_ui.pushButton_Save.clicked.connect(self.save_date)
self.password_ui.pushButton_Delete.clicked.connect(self.delete_date)
self.password_ui.tableWidget.cellChanged.connect(self.change_cell)
def init_date(self):
if len(self.db.tables_name) == 0 or TABLE_NAME not in self.db.tables_name[0]:
self.create_table()
self.play_header(TABLE_NAME)
self.db.operation("select * from {}".format(TABLE_NAME))
all_date = [list(date) for date in self.db.get_query_date()] # 数据类型是 列表-元组,,元组不可改变,需要查询的数据做类型转换
# 加密的数据进行解密,如果解密失败的话,用原值记录
for i in range(len(all_date)):
for j in range(len(all_date[i])):
if j >= 2: # 前两列不需要做加解密,记录的是原文,后面的数据保存是做加密保存的
decrypt_text = self.skf.ECCDecrypt_Hex(all_date[i][j])
if decrypt_text != "Error: Wrong ciphertext!": # 解密失败返回的结果
all_date[i][j] = decrypt_text
return all_date
def create_table(self):
sql = r'create table {0}' \
r'({1} INT PRIMARY KEY NOT NULL,' \
r'{2} text,' \
r'{3} text,' \
r'{4} text);'.format(TABLE_NAME, TABLE_FIELD[0], TABLE_FIELD[1], TABLE_FIELD[2], TABLE_FIELD[3])
self.db.operation(sql, commit=True)
def load_date(self):
all_date = self.init_date() # 获取数据库的所有数据
for i in range(len(all_date)): # 显示所有数据
self.password_ui.tableWidget.insertRow(i)
for j in range(len(all_date[i])):
item = QTableWidgetItem()
if j == 0: # ID列,不可修改
item.setText(str(all_date[i][j]))
item.setFlags(Qt.ItemIsEnabled) # 参数名字段不允许修改
item.setTextAlignment(Qt.AlignCenter)
else:
item.setText(all_date[i][j])
self.password_ui.tableWidget.setItem(i, j, item)
# 清楚数据,将加载数据按键置灰
self.change_date.clear()
self.password_ui.pushButton_LoadDate.setEnabled(False)
self.password_ui.pushButton_Save.setEnabled(False)
def play_header(self, table_name):
table_filed = self.db.get_table_filed(table_name)
for i in range(len(table_filed)):
# 插入一列
self.password_ui.tableWidget.insertColumn(i)
# 设置header内容
item = QTableWidgetItem()
item.setText(table_filed[i])
self.password_ui.tableWidget.setHorizontalHeaderItem(i, item)
def add_row(self):
row_num = self.password_ui.tableWidget.rowCount() # 获取当前显示的行数
self.password_ui.tableWidget.insertRow(row_num) # 插入新的一行
item = QTableWidgetItem() # 定义item
if row_num == 0: # 当前数据为空的时候,设置ID列的值,为row_num+1
item.setText(str(row_num + 1))
self.add_id.append(str(row_num + 1)) # 记录新增id值,,用与后续保存操作
else: # 表格内有数据的时候,新增的ID为最后一个值+1
id_text = self.password_ui.tableWidget.item(row_num - 1, 0).text() # 获取表格最后一个ID的值
item.setText(str(int(id_text) + 1)) # 设置新增的ID
self.add_id.append(str(int(id_text) + 1)) # 记录新增id值,,用与后续保存操作
item.setFlags(Qt.ItemIsEnabled) # 参数名字段不允许修改
item.setTextAlignment(Qt.AlignCenter)
self.password_ui.tableWidget.setItem(row_num, 0, item)
self.password_ui.pushButton_Save.setEnabled(True)
def change_cell(self, row, column):
date = {} # 定义修改的数据字典
cell_text = self.password_ui.tableWidget.item(row, column).text() # 获取修改表格的内容
header_item = self.password_ui.tableWidget.horizontalHeaderItem(column) # 获取对应的标题item
header_text = header_item.text() # 获取对应的标题
id_ = self.password_ui.tableWidget.item(row, 0).text() # 当前修改行所对应的ID
if header_text in ["ACCOUNT", "PASSWORD"]: # 判断当前数据是否需要进行加密
cell_text = self.skf.ECCEncrypt_Hex(cell_text)
date[header_text] = cell_text # 修改内容,字典类型
if id_ in self.add_id: # 判断是不是在新增的数据内
if id_ not in self.add_date: # 只新增了行,其他数据内容未更改
self.add_date[id_] = date
else: # 记录修改的内容
self.add_date[id_][header_text] = cell_text
else: # 修改的数据
if id_ not in self.change_date:
self.change_date[id_] = date
else:
self.change_date[id_][header_text] = cell_text
self.password_ui.pushButton_Save.setEnabled(True) # 执行保存数据操作
def save_date(self):
if self.change_date is not None:
for date_item in self.change_date.items():
date = date_item[1].items()
set_date = ",".join(["{}='{}'".format(filed[0], filed[1]) for filed in date])
sql = "update {} set {} where ID={}".format(TABLE_NAME, set_date, date_item[0])
self.db.operation(sql, commit=True)
if self.add_date is not None:
for date_item in self.add_date.items():
date = date_item[1].items()
field = [filed[0] for filed in date]
value = [value[1] for value in date]
value[0] = int(value[0])
insert_field = ",".join(field)
insert_value = tuple(value)
if len(insert_value) == 1:
insert_value = "()" + insert_value[0]
sql = "insert into {0} ({1}) values{2}".format(TABLE_NAME, insert_field, insert_value)
self.db.operation(sql, commit=True)
self.password_ui.pushButton_Save.setEnabled(False)
self.add_id = []
self.add_date.clear()
self.change_date.clear()
def delete_date(self):
currentrow = self.password_ui.tableWidget.currentRow()
id_text = self.password_ui.tableWidget.item(currentrow, 0).text()
header_item = self.password_ui.tableWidget.horizontalHeaderItem(0)
header_text = header_item.text()
sql = "delete from {} where {}={}".format(TABLE_NAME, header_text, id_text)
self.db.operation(sql, commit=True)
self.password_ui.tableWidget.removeRow(currentrow)
# 如果删除的数据在add_date,或change_date中,要把对应的数据给清楚
if id_text in self.add_id:
self.add_id.remove(id_text)
if id_text in self.add_date:
self.add_date.pop(id_text)
if id_text in self.change_date:
self.change_date.pop(id_text)
if len(self.add_id) == 0 and len(self.add_date) == 0 and len(self.change_date) == 0:
self.password_ui.pushButton_Save.setEnabled(False)
class play:
login_ui = None
function_ui = None
app = QApplication([])
play.login_ui = WinLogin(myskf)
play.login_ui.login_ui.show()
app.exec_()