如何用SQLite实现用户持久登录及信息更新功能?
解决方案
一、调整数据库表结构
原表将gmail设为主键,无法直接修改用户邮箱,需新增自增用户ID作为主键,同时给gmail添加唯一约束保证不重复。另外,为实现持久登录,需新增存储登录token和过期时间的字段:
def createTable(): conn = sql.connect('user_data.db') print("Opened database successfully") conn.execute('''CREATE TABLE user_info( user_id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, gmail TEXT NOT NULL UNIQUE, password TEXT NOT NULL, value REAL, login_token TEXT, token_expiry DATETIME );''') print("Table created successfully") conn.close()
二、实现用户信息更新功能
1. 更新姓名
def update_username(user_id, new_name): conn = sql.connect('user_data.db') cursor = conn.cursor() try: cursor.execute("UPDATE user_info SET name = ? WHERE user_id = ?", (new_name, user_id)) conn.commit() return True except Exception as e: print(f"更新姓名失败: {e}") conn.rollback() return False finally: conn.close()
2. 更新密码
def update_password(user_id, new_password): # 注意:生产环境必须加密存储密码,示例用bcrypt(需提前安装:pip install bcrypt) import bcrypt hashed_pw = bcrypt.hashpw(new_password.encode('utf-8'), bcrypt.gensalt()) conn = sql.connect('user_data.db') cursor = conn.cursor() try: cursor.execute("UPDATE user_info SET password = ? WHERE user_id = ?", (hashed_pw, user_id)) conn.commit() return True except Exception as e: print(f"更新密码失败: {e}") conn.rollback() return False finally: conn.close()
3. 更新Gmail
def update_gmail(user_id, new_gmail): conn = sql.connect('user_data.db') cursor = conn.cursor() try: # 先检查新邮箱是否已被占用 cursor.execute("SELECT user_id FROM user_info WHERE gmail = ?", (new_gmail,)) if cursor.fetchone() is not None: print("该Gmail已被注册") return False cursor.execute("UPDATE user_info SET gmail = ? WHERE user_id = ?", (new_gmail, user_id)) conn.commit() return True except Exception as e: print(f"更新Gmail失败: {e}") conn.rollback() return False finally: conn.close()
三、修改登录逻辑(支持标识符+密码登录+持久登录)
1. 登录函数
import uuid from datetime import datetime, timedelta import bcrypt def login(identifier=None, password=None, token=None): conn = sql.connect('user_data.db') cursor = conn.cursor() user = None if token: # 持久登录验证:检查token是否有效且未过期 cursor.execute("SELECT * FROM user_info WHERE login_token = ? AND token_expiry > ?", (token, datetime.now())) user = cursor.fetchone() if user: # 延长token有效期至7天后 new_expiry = datetime.now() + timedelta(days=7) cursor.execute("UPDATE user_info SET token_expiry = ? WHERE user_id = ?", (new_expiry, user[0])) conn.commit() elif identifier and password: # 支持通过姓名/Gmail作为标识符,搭配密码登录 cursor.execute("SELECT * FROM user_info WHERE (name = ? OR gmail = ?)", (identifier, identifier)) user = cursor.fetchone() if user and bcrypt.checkpw(password.encode('utf-8'), user[3]): # 生成唯一持久登录token login_token = str(uuid.uuid4()) token_expiry = datetime.now() + timedelta(days=7) cursor.execute("UPDATE user_info SET login_token = ?, token_expiry = ? WHERE user_id = ?", (login_token, token_expiry, user[0])) conn.commit() return {"success": True, "user": user, "login_token": login_token} conn.close() if user: return {"success": True, "user": user} else: return {"success": False, "message": "登录失败,信息有误或token过期"}
2. 关键说明
- 仅密码登录的风险:若仅靠密码登录,当多个用户密码相同时无法区分用户,建议保留「姓名/Gmail+密码」的登录方式,持久登录状态下可自动填充标识符,用户仅需输入密码即可完成验证。
- 密码加密:生产环境必须使用加密算法存储密码,示例中用
bcrypt实现密码的哈希与验证,绝对禁止明文存储。
四、持久登录的前端处理示例
如果是Web应用,登录成功后将返回的login_token存储在浏览器的cookie中;下次用户访问时,前端自动携带该token,后端调用login(token=token)即可完成持久登录验证。
内容的提问来源于stack exchange,提问作者Parsa_Dev
相关产品推荐
相关产品推荐

