【Python】个人账号密码管理Demo

【Python】个人账号密码管理Demo

各个平台、网站都有要设置对应的账号密码,太多账号密码需要记住,经常容易搞混或者忘记,需要找回密码。结合前面学到的使用Ukey对数据的加解密以及可视化Pyside2,想到用这些完成个人账号密码的管理,可以用来记录自己各个账号密码。

1-主要内容

  • SKF接口库的调用——完成对数据的加解密
  • Pyside2的使用——可视化的实现
  • 接口库sqlite3——数据库的使用,用于账号密码的存储

2-实现过程

2.1-数据的加解密

有关使用Ukey完成对数据的加解密可以参考python-使用U盾完成数据的加解密(使用国密算法SKF接口)

2.2-界面的设置

(1)登录界面

参考下方链接的登录界面实现

python-U盾数据加解密可视化_pyside2

(2)账号密码管理界面

功能:

  • 加载数据:读取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)

2.3-接口库sqlite3的使用

为了方便使用sqlite3库,由此封装一个自己的类,主要的功能有:

  • def __connect_db(self, db_name):连接或者创建数据库
  • def operation(self, str_sql, commit=False):传入Sql语句,执行操作,默认commit=False,若执行insert,update,delete操作需要传True
  • def 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__:关闭相关的句柄

3-代码部分

3.1-SKF加解密代码

Python-使用U盾完成数据的加解密(使用国密算法SKF接口)

3.2-封装sqlite3实现代码

#!/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()

3.3-Pyside2可视化实现代码

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_()

4-结果展示

4.1 未插入key登录的情况

Ukey未插入

4.2插入key,但是PIN错误的情况

下方会提示Ukey的剩余尝试次数
在这里插入图片描述

4.3 登录成功并加载数据的情况

在这里插入图片描述

4.4 直接读取MyPassword.db显示的数据

在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值