一个用于管理Streamlit应用程序用户访问的安全认证模块
目录
安装
Streamlit-Authenticator通过PyPI分发:
pip install streamlit-authenticator
欢迎测试演示应用。
示例
使用Streamlit-Authenticator非常简单,只需导入模块并调用它来验证用户的凭据。
import streamlit as st
import streamlit_authenticator as stauth
1. 创建配置文件
- 首先创建一个YAML配置文件,定义用户的凭据:包括姓名、用户名和密码(明文密码将自动哈希)。
- 此外,输入名称、随机密钥和过期天数,用于存储在客户端浏览器上的重新认证cookie,以实现无密码重新认证。如果不需要重新认证,可以将过期天数设置为0。
- 最后,定义一个预授权电子邮件列表,这些用户可以注册并使用register_user小部件将他们的凭据添加到配置文件中。
- 请记住在使用reset_password、register_user、forgot_password或update_user_details小部件后更新配置文件(如步骤10所示)。
credentials:
usernames:
jsmith:
email: jsmith@gmail.com
failed_login_attempts: 0 # 将自动管理
logged_in: False # 将自动管理
name: John Smith
password: abc # 将自动哈希
rbriggs:
email: rbriggs@gmail.com
failed_login_attempts: 0 # 将自动管理
logged_in: False # 将自动管理
name: Rebecca Briggs
password: def # 将自动哈希
cookie:
expiry_days: 30
key: some_signature_key # 必须为字符串
name: some_cookie_name
pre-authorized:
emails:
- melsby@gmail.com
- 请注意,凭据中与每个用户的失败登录尝试次数和登录状态相对应的'failed_login_attempts'和'logged_in'字段将自动添加和管理。
2. 设置
- 随后将配置文件导入到你的脚本中,并创建一个认证对象。
import yaml
from yaml.loader import SafeLoader
with open('../config.yaml') as file:
config = yaml.load(file, Loader=SafeLoader)
# 一次性预哈希所有明文密码
# Hasher.hash_passwords(config['credentials'])
authenticator = stauth.Authenticate(
config['credentials'],
config['cookie']['name'],
config['cookie']['key'],
config['cookie']['expiry_days'],
config['pre-authorized']
)
- 默认情况下,明文密码将自动哈希,但对于大量用户,建议使用Hasher.hash_passwords函数预先哈希凭据中的密码。
- 如果选择预先哈希密码,请将Authenticate类中的auto_hash参数设置为False。
Hasher.hash_passwords
参数:
- credentials: dict
- 包含明文密码的凭据字典。
返回:
- dict
- 包含哈希密码的凭据字典。
Authenticate
参数:
- credentials: dict
- 提供用户名、姓名、密码、电子邮件和其他用户数据。
- cookie_name: str
- 指定存储在客户端浏览器上用于无密码重新认证的cookie的名称。
- cookie_key: str
- 指定用于哈希重新认证cookie签名的密钥。
- cookie_expiry_days: float, 默认30.0
- 指定重新认证cookie在客户端浏览器上自动过期的天数。
- pre_authorized: list, 可选, 默认None
- 提供未注册但被授权注册的用户的电子邮件列表。
- validator: Validator, 可选, 默认None
- 提供一个验证器对象,用于检查用户名、姓名和电子邮件字段的有效性。
- auto_hash: bool, 默认True
- 密码自动哈希要求,True:明文密码将自动哈希,False:明文密码不会自动哈希。
- 请记住在多页应用程序中将authenticator对象作为会话状态变量传递给每个页面。
3. 创建登录小部件
- 你可以按如下方式渲染登录小部件。
authenticator.login()
Authenticate.login
参数:
- location: 字符串,{'main', 'sidebar', 'unrendered'},默认值为'main'
- 指定登录小部件的位置。
- max_concurrent_users: 整数,可选,默认值为None
- 限制并发用户数量。如果未指定,则不限制同时登录的用户数量。
- max_login_attempts: 整数,可选,默认值为None
- 限制失败登录尝试次数。如果未指定,则不限制失败登录尝试次数。
- fields: 字典,可选,默认值为{'Form name':'Login', 'Username':'Username', 'Password':'Password', 'Login':'Login'}
- 自定义标题、按钮和其他字段的文本。
- captcha: 布尔值,默认值为False
- 指定登录小部件的验证码要求,True:需要验证码,False:移除验证码。
- clear_on_submit: 布尔值,默认值为False
- 指定提交时清除设置,True:提交时清除输入,False:提交时保留输入。
- key: 字符串,默认值为'Login'
- 提供给小部件的唯一键,以避免重复的WidgetID错误。
- callback: 可调用对象,可选,默认值为None
- 可选的回调函数,在表单提交时调用,参数为一个字典。
- sleep_time: 浮点数,可选,默认值为None
- 登录小部件的可选睡眠时间。
返回值:
- 字符串
- 已认证用户的姓名。
- 布尔值
- 认证状态,None:未输入凭据,False:凭据不正确,True:凭据正确。
- 字符串
- 已认证用户的用户名。
- 请记住在多页应用程序的每个页面上重新调用"unrendered"登录小部件。
4. 认证用户
- 然后,您可以使用st.session_state['name']、**st.session_state['authentication_status']和st.session_state['username']**从Streamlit的会话状态中检索姓名、认证状态和用户名,以允许已验证的用户访问受限内容。
- 您还可以渲染一个注销按钮,或者选择不渲染该按钮,如果您只需要以编程方式实现注销逻辑。
- 注销按钮的可选key参数应在多页应用程序中使用,以防止Streamlit抛出重复键错误。
if st.session_state['authentication_status']:
authenticator.logout()
st.write(f'欢迎 *{st.session_state["name"]}*')
st.title('一些内容')
elif st.session_state['authentication_status'] is False:
st.error('用户名/密码不正确')
elif st.session_state['authentication_status'] is None:
st.warning('请输入您的用户名和密码')
Authenticate.logout
参数:
- button_name: 字符串,默认值为'Logout'
- 自定义按钮名称。
- location: 字符串,{'main', 'sidebar', 'unrendered'},默认值为'main'
- 指定注销按钮的位置。如果传入'unrendered',将执行注销逻辑而不渲染按钮。
- key: 字符串,默认值为None
- 应在多页应用程序中使用的唯一键。
- callback: 可调用对象,可选,默认值为None
- 可选的回调函数,在表单提交时调用,参数为一个字典。
- 或提示未验证的用户输入正确的用户名和密码。
- 您还可以通过访问**st.session_state['failed_login_attempts']**来检索用户的失败登录尝试次数,该值返回一个字典,以用户名为键,失败尝试次数为值。
5. 创建重置密码小部件
- 您可以使用reset_password小部件允许已登录用户修改其密码,如下所示。
if st.session_state['authentication_status']:
try:
if authenticator.reset_password(st.session_state['username']):
st.success('密码修改成功')
except Exception as e:
st.error(e)
Authenticate.reset_password
参数:
- username: 字符串
- 指定要重置密码的用户的用户名。
- location: 字符串,{'main', 'sidebar'},默认值为'main'
- 指定重置密码小部件的位置。
- fields: 字典,可选,默认值为{'Form name':'Reset password', 'Current password':'Current password', 'New password':'New password', 'Repeat password': 'Repeat password', 'Reset':'Reset'}
- 自定义标题、按钮和其他字段的文本。
- clear_on_submit: 布尔值,默认值为False
- 指定提交时清除设置,True:提交时清除输入,False:提交时保留输入。
- key: 字符串,默认值为'Reset password'
- 提供给小部件的唯一键,以避免重复的WidgetID错误。
- callback: 可调用对象,可选,默认值为None
- 可选的回调函数,在表单提交时调用,参数为一个字典。
返回值:
- 布尔值
- 重置密码的状态。
- 请记住在使用此小部件后更新配置文件(如步骤10所示)。
6. 创建新用户注册小部件
- 您可以使用register_user小部件允许用户注册您的应用程序,如下所示。
- 如果您要求用户预先授权,请将pre_authorization参数设置为True,并将其电子邮件添加到配置文件中的pre_authorized列表中。
- 一旦他们注册,他们的电子邮件将自动从配置文件中的pre_authorized列表中删除。
- 或者,要允许任何人注册,请将pre_authorization参数设置为False。
try:
email_of_registered_user, username_of_registered_user, name_of_registered_user = authenticator.register_user(pre_authorization=False)
if email_of_registered_user:
st.success('用户注册成功')
except Exception as e:
st.error(e)
Authenticate.register_user
参数:
- location: 字符串,{'main', 'sidebar'},默认值为'main'
- 指定注册用户小部件的位置。
- pre_authorization: 布尔值,默认值为True
- 指定预授权要求,True:用户必须预先授权才能注册,False:任何用户都可以注册。
- domains: 列表,可选,默认值为None
- 指定新电子邮件必须属于的域列表,例如['gmail.com', 'yahoo.com'],列表:必需的域列表,None:允许任何域。
- fields: 字典,可选,默认值为{'Form name':'Register user', 'Email':'Email', 'Username':'Username', 'Password':'Password', 'Repeat password':'Repeat password', 'Register':'Register'}
- 自定义标题、按钮和其他字段的文本。
- captcha: 布尔值,默认值为True
- 指定注册用户小部件的验证码要求,True:需要验证码,False:移除验证码。
- clear_on_submit: 布尔值,默认值为False
- 指定提交时清除设置,True:提交时清除输入,False:提交时保留输入。
- key: 字符串,默认值为'Register user'
- 提供给小部件的唯一键,以避免重复的WidgetID错误。
- callback: 可调用对象,可选,默认值为None
- 可选的回调函数,在表单提交时调用,参数为一个字典。
返回值:
- 字符串
- 与新用户关联的电子邮件。
- 字符串
- 与新用户关联的用户名。
- 字符串
- 与新用户关联的姓名。
- 请记得在使用此小部件后更新配置文件(如步骤10所示)。
7. 创建忘记密码小部件
- 您可以使用 forgot_password 小部件允许用户生成新的随机密码。
- 新密码将自动进行哈希处理并保存在配置文件中。
- 该小部件将返回用户名、电子邮件和新的随机密码,开发人员随后应当安全地将其传送给用户。
try:
username_of_forgotten_password, email_of_forgotten_password, new_random_password = authenticator.forgot_password()
if username_of_forgotten_password:
st.success('新密码将被安全发送')
# 开发人员应当安全地将新密码传送给用户。
elif username_of_forgotten_password == False:
st.error('未找到用户名')
except Exception as e:
st.error(e)
Authenticate.forgot_password
参数
- location: str, {'main', 'sidebar'}, 默认值 'main'
- 指定忘记密码小部件的位置。
- fields: dict, 可选, 默认值 {'Form name':'Forgot password', 'Username':'Username', 'Submit':'Submit'}
- 自定义标题、按钮和其他字段的文本。
- captcha: bool, 默认值 False
- 指定忘记密码小部件的验证码要求,True:需要验证码,False:移除验证码。
- clear_on_submit: bool, 默认值 False
- 指定提交时清除设置,True:提交时清除输入,False:提交时保留输入。
- key: str, 默认值 'Forgot password'
- 提供给小部件的唯一键,以避免重复的WidgetID错误。
- callback: callable, 可选, 默认值 None
- 可选的回调函数,将在表单提交时调用,参数为一个字典。
返回值:
- str
- 与忘记的密码关联的用户名。
- str
- 与忘记的密码关联的电子邮件。
- str
- 应当安全传送给用户的新明文密码。
- 请记得在使用此小部件后更新配置文件(如步骤10所示)。
8. 创建忘记用户名小部件
- 您可以使用 forgot_username 小部件允许用户检索他们忘记的用户名。
- 该小部件将返回用户名和电子邮件,开发人员随后应当安全地将其传送给用户。
try:
username_of_forgotten_username, email_of_forgotten_username = authenticator.forgot_username()
if username_of_forgotten_username:
st.success('用户名将被安全发送')
# 开发人员应当安全地将用户名传送给用户。
elif username_of_forgotten_username == False:
st.error('未找到电子邮件')
except Exception as e:
st.error(e)
Authenticate.forgot_username
参数
- location: str, {'main', 'sidebar'}, 默认值 'main'
- 指定忘记用户名小部件的位置。
- fields: dict, 可选, 默认值 {'Form name':'Forgot username', 'Email':'Email', 'Submit':'Submit'}
- 自定义标题、按钮和其他字段的文本。
- captcha: bool, 默认值 False
- 指定忘记用户名小部件的验证码要求,True:需要验证码,False:移除验证码。
- clear_on_submit: bool, 默认值 False
- 指定提交时清除设置,True:提交时清除输入,False:提交时保留输入。
- key: str, 默认值 'Forgot username'
- 提供给小部件的唯一键,以避免重复的WidgetID错误。
- callback: callable, 可选, 默认值 None
- 可选的回调函数,将在表单提交时调用,参数为一个字典。
返回值:
- str
- 应当安全传送给用户的忘记的用户名。
- str
- 与忘记的用户名关联的电子邮件。
9. 创建更新用户详情小部件
- 您可以使用 update_user_details 小部件允许已登录的用户更新他们的姓名和/或电子邮件。
- 该小部件将自动在配置文件和重新认证cookie中保存更新后的详情。
if st.session_state['authentication_status']:
try:
if authenticator.update_user_details(st.session_state['username']):
st.success('条目更新成功')
except Exception as e:
st.error(e)
Authenticate.update_user_details
参数
- username: str
- 指定要更新用户详情的用户名。
- location: str, {'main', 'sidebar'}, 默认值 'main'
- 指定更新用户详情小部件的位置。
- fields: dict, 可选, 默认值 {'Form name':'Update user details', 'Field':'Field', 'Name':'Name', 'Email':'Email', 'New value':'New value', 'Update':'Update'}
- 自定义标题、按钮和其他字段的文本。
- clear_on_submit: bool, 默认值 False
- 指定提交时清除设置,True:提交时清除输入,False:提交时保留输入。
- key: str, 默认值 'Update user details'
- 提供给小部件的唯一键,以避免重复的WidgetID错误。
- callback: callable, 可选, 默认值 None
- 可选的回调函数,将在表单提交时调用,参数为一个字典。
返回值:
- bool
- 更新用户详情的状态。
- 请记得在使用此小部件后更新配置文件(如步骤10所示)。
10. 更新配置文件
- 请确保在凭据更新或使用 reset_password、register_user、forgot_password 或 update_user_details 小部件后重新保存配置文件。
with open('../config.yaml', 'w') as file:
yaml.dump(config, file, default_flow_style=False)
许可证
本项目为专有软件。本软件的使用受 LICENSE 文件中指定的条款约束。未经授权复制、修改或分发本软件是禁止的。