给 PyQt5 登录添加记住用户密码功能,并优化一些内容

使用 PyQt5(PySide2)+SQLAlchemy 做一个登录注册页(七)完结

本文将介绍自己用 PyQt5+SQLAlchemy 做的一个登录注册页,使用邮箱接收验证码本文介绍是前后端未分离的实现方式,后续将出一个前后端分离的,你可以将 PyQt5 改为 PySide2 以获得更宽松的开源协议

本文由于涉及到的代码较多,将会是一个系列,会有多篇文章

系列文章索引

  1. 设计登录注册页面
  2. 添加代码运行登录注册页,并为其添加一些样式,和调用资源文件
  3. 使用 SQLAlchemy 实现用户数据库管理
  4. 为登录页,添加登录逻辑代码,实现登录
  5. 给注册页,添加注册逻辑代码,实现用户的注册验证
  6. 给忘记密码页,添加逻辑,实现密码找回
  7. 给登录添加记住用户密码功能,并优化一些内容

必要说明

  • 使用的环境 requirements.txt
  • 项目结构(显示变化的部分)
--- QtLoginRegistration
  |--- lib
     |--- crypto.py               # 本地密码的存储
  |--- requirements.txt           # 添加 pywin32

给登录添加记住用户密码功能,并优化一些内容(完结)

注意:记住的密码保存在本地,虽然加密了,但是这依然存在泄露的风险(好比浏览器的保存密码),请酌情使用。你还可以使用 sqlcipher 来加密 SQLite整个文件 这样更安全 看这里 使用 sqlcipher 来增强本地数据的安全性

第1步

添加lib/crypto.py,实现本地密码的存储,密码通过加密,存放在SQLite中,且只支持 Windows,因为使用的PyWin32库,同时也因此原因,只能使用32位的Python,这里还补充一种使用文本混淆的方式,来保存密码,不要求 32 位的 Python 可以见这里

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
"""
@ Project     : QtLoginRegistration
@ File        : crypto.py
@ Author      : yqbao
@ Version     : V1.0.0
@ Description : 
"""
import sqlite3

import win32crypt


def crypto(password):
    encrypt = win32crypt.CryptProtectData(password.encode('utf-8'))
    return encrypt


def create_db(db, table):
    conn = sqlite3.connect(db)
    cursor = conn.cursor()
    try:
        cursor.execute(f'CREATE TABLE {table} (username text , password text)')
        conn.commit()
    except sqlite3.OperationalError:
        pass
    conn.close()


def insert_db(db, table, username, password):
    conn = sqlite3.connect(db)
    cursor = conn.cursor()
    encrypt = crypto(password)
    cursor.execute(f"INSERT INTO {table}(username,password) VALUES(?,?)", (username, encrypt))
    conn.commit()
    conn.close()


def delete_db(db, table):
    conn = sqlite3.connect(db)
    cursor = conn.cursor()
    cursor.execute(f"DELETE FROM {table}")
    conn.commit()
    conn.close()


def decrypt(db, table):
    conn = sqlite3.connect(db)
    cursor = conn.cursor()
    cursor.execute(f"SELECT * FROM {table}")
    result = cursor.fetchall()[-1]
    username = result[0]
    password = win32crypt.CryptUnprotectData(result[1])[-1]
    password = password.decode('utf-8')
    return username, password


if __name__ == '__main__':
    db_ = 'test.db'
    table_ = 'test'
    create_db(db_, table_)
    delete_db(db_, table_)
    insert_db(db_, table_, 'test', '111111')
    print(decrypt(db_, table_))

效果如下:
image

image


第2步

添加记住功能

  1. 校验被记住的用户和密码
def remember_required(self):
    """参数校验"""
    try:
        self.username, self.password = crypto.decrypt(self.accounts, self.table)
        if not self.username.strip() or not self.password.strip():
            return False
    except IndexError:
        return False
    return True

  1. 实现存储
def remember(self):
    """记住"""
    if not self.checkBox.isChecked():
        crypto.delete_db(self.accounts, self.table)
        return
    crypto.delete_db(self.accounts, self.table)
    crypto.insert_db(self.accounts, self.table, self.account, self.password)

  1. 启动时,初始化
def remember_init(self):
    """初始化"""
    if not self.remember_required():
        return
    self.lineEditUsername.setText(self.username)
    self.lineEditPassword.setText(self.password)
    return True
  1. 调用
# 在 init_ui 初始化中调用
self.accounts = 'remember.db'
self.table = 'remember'
crypto.create_db(self.accounts, self.table)  # 创建存储库
self.remember_init()

# login 方法中添加 记住方法调用

def login(self):
    """登录动作"""
    ...  # 省略
    self.remember()

第3步

优化窗口切换,则清空输入的内容

# 在 init_ui 添加窗口切换信号
self.stackedWidget.currentChanged.connect(self.update_stacked_widget)

# 清空输入
def update_stacked_widget(self):
    self.lineEditUsername.clear()
    self.lineEditPassword.clear()
    self.lineEdit.clear()
    self.lineEdit_2.clear()
    self.lineEdit_3.clear()
    self.lineEdit_4.clear()
    self.lineEdit_5.clear()
    self.lineEdit_6.clear()
    self.lineEdit_7.clear()
    self.lineEdit_8.clear()
    self.lineEdit_9.clear()

GitHub完整代码
本文章的原文地址
GitHub主页

posted @ 2024-02-21 13:21  星尘的博客  阅读(235)  评论(0编辑  收藏  举报