You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Streamlit应用中保存用户信息并实现刷新保持登录状态

Streamlit 实现页面刷新后保持登录状态的方案

用Cookie实现页面刷新后保持登录完全可行,这是Web应用中实现持久化会话的标准方案之一。下面是具体的实现思路和代码示例:

核心思路

  1. 登录成功后生成会话令牌:用户登录验证通过后,生成一个唯一且不可伪造的会话令牌,将令牌存入Cookie,同时在数据库中记录令牌对应的用户ID和过期时间。
  2. 页面加载时验证令牌:每次页面刷新或打开新会话时,先读取Cookie中的令牌,验证其在数据库中是否存在且未过期,验证通过则自动登录用户。

代码实现

首先需要安装Cookie管理依赖:

pip install streamlit-cookie-manager

然后编写核心逻辑:

import streamlit as st
from streamlit_cookie_manager import CookieManager
import uuid
import datetime
import sqlite3
import bcrypt  # 用于密码哈希,注册环节需同步使用该工具加密密码

# 初始化Cookie管理器
cookie_manager = CookieManager()

# 连接数据库(假设已存在users表,包含id、name、hashed_password字段)
conn = sqlite3.connect('school_app.db')
c = conn.cursor()

# 确保sessions表存在,用于存储会话令牌
c.execute('''
CREATE TABLE IF NOT EXISTS sessions (
    token TEXT PRIMARY KEY,
    user_id INTEGER,
    expires_at TEXT,
    FOREIGN KEY(user_id) REFERENCES users(id)
)
''')
conn.commit()

def validate_session_token(token):
    """验证会话令牌是否有效"""
    c.execute('SELECT user_id, expires_at FROM sessions WHERE token = ?', (token,))
    session = c.fetchone()
    if not session:
        return None
    
    user_id, expires_at_str = session
    expires_at = datetime.datetime.fromisoformat(expires_at_str)
    if datetime.datetime.now() > expires_at:
        # 令牌过期,清理无效会话
        c.execute('DELETE FROM sessions WHERE token = ?', (token,))
        conn.commit()
        return None
    
    return user_id

def create_new_session(user_id):
    """为用户创建新的会话令牌"""
    # 先删除用户已有会话,避免多端登录(可选逻辑)
    c.execute('DELETE FROM sessions WHERE user_id = ?', (user_id,))
    
    token = str(uuid.uuid4())  # 生成唯一随机令牌
    expires_at = datetime.datetime.now() + datetime.timedelta(days=7)  # 设置7天过期
    
    c.execute('INSERT INTO sessions (token, user_id, expires_at) VALUES (?, ?, ?)',
              (token, user_id, expires_at.isoformat()))
    conn.commit()
    return token, expires_at

# 页面初始化时检查会话状态
current_user = None
token = cookie_manager.get('session_token')
if token:
    user_id = validate_session_token(token)
    if user_id:
        # 获取当前用户信息
        c.execute('SELECT name FROM users WHERE id = ?', (user_id,))
        current_user = c.fetchone()[0]

# 根据登录状态渲染对应页面
if not current_user:
    st.title('用户登录')
    name = st.text_input('姓名')
    password = st.text_input('密码', type='password')
    
    if st.button('登录'):
        # 验证用户密码(数据库中存储的是哈希后的密码)
        c.execute('SELECT id, hashed_password FROM users WHERE name = ?', (name,))
        user = c.fetchone()
        if user:
            user_id, hashed_pw = user
            if bcrypt.checkpw(password.encode('utf-8'), hashed_pw):
                # 登录成功,创建会话并设置Cookie
                token, expires_at = create_new_session(user_id)
                cookie_manager.set('session_token', token, expires_at=expires_at, httponly=True)
                st.rerun()
            else:
                st.error('密码错误')
        else:
            st.error('用户不存在')
else:
    st.title(f'欢迎回来,{current_user}!')
    if st.button('退出登录'):
        # 清理Cookie和数据库中的会话记录
        cookie_manager.delete('session_token')
        c.execute('DELETE FROM sessions WHERE user_id = ?', (user_id,))
        conn.commit()
        st.rerun()

conn.close()

关键注意事项

  • 密码安全:绝对不能明文存储密码,注册用户时必须用bcrypt这类哈希算法加密后再存入数据库。
  • 令牌安全性:使用UUID生成随机令牌,避免被恶意猜测;开启Cookie的httponly属性,防止XSS攻击窃取Cookie内容。
  • 令牌过期:设置合理的过期时间,过期后自动清理数据库中的无效会话,避免资源浪费。
  • HTTPS部署:如果应用部署在公网环境,一定要启用HTTPS,并开启Cookie的secure属性,确保Cookie仅通过加密通道传输。

内容的提问来源于stack exchange,提问作者Daniel Phillion

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.11 19:33:15