原文:
towardsdatascience.com/implementing-streamlit-authenticator-across-multi-page-apps-5ad70ac315b3
简介
Streamlit 是一个广泛使用的工具,用于创建由数据支持的数据快速网络应用,但它不具备管理多个用户并在他们使用应用时识别他们的能力。
Streamlit 提供了一些基本的文档,说明如何通过在secrets.toml文件中使用硬编码的键值对来添加此功能,然而这确实是一种非常简单的方法,你可能会很快就会觉得它不够用!
幸运的是,开发者 Mohammad Khorasani 编写了一个非常出色的包,以非常简单而优雅的方式添加了相当复杂的验证功能!它被称为 Streamlit Authenticator,可在 GitHub 上找到,并且可以使用你喜欢的包管理器,如 PIP 进行安装。
Mohammad 提供了一个很好的示例应用和代码,用于单页面应用,但没有多页面应用的示例。我决定为任何有兴趣使用它的人提供一个起点。我还检查了作者,以确保代码是正确的。
如果你想要立即开始,这里是你入门应用的完整代码。
https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/ce254785e601e56a02f49e950e328eb5.png
图片由作者提供
多页面应用的挑战
你在多页面应用中遇到的主要问题是需要正确管理 Streamlit 会话状态。登录后,你需要正确持久化认证信息,检查用户是否已登录,并相应地展示正确的信息。
请记住,在多页面应用中,要将验证器对象作为会话状态变量传递给每个页面。
文档中有一些关于多页面应用的注释,例如上面的内容,但并不足以让你轻松上手。
设置初始验证器
首先创建Home.py文件,它将是应用的入口点。我们需要标准导入和一些基本代码来构建 Streamlit 应用。
importstreamlitasstimportstreamlit_authenticatorasstauthfromstreamlit_authenticator.utilitiesimportLoginErrorimportyamlfromyaml.loaderimportSafeLoader st.title("Streamlit-Authenticator")接下来,根据设置指南,我们可以添加所需信息以读取 config.yaml 文件(参见文档了解这一切是如何工作的)。
# Load credentials from the YAML filewithopen("config.yaml")asfile:config=yaml.load(file,Loader=SafeLoader)# Initialize the authenticatorauthenticator=stauth.Authenticate(config["credentials"],config["cookie"]["name"],config["cookie"]["key"],config["cookie"]["expiry_days"],)接下来,我们需要根据文档中的引言设置会话状态。以下是我们的实现方式。
# Store the authenticator object in the session statest.session_state["authenticator"]=authenticator# Store the config in the session state so it can be updated laterst.session_state["config"]=config注意,除了认证器对象外,我们还在存储从上面的文件中读取的配置。这允许我们在配置文件更新时(例如更改密码)稍后将其写出来。最后,我们渲染登录小部件,并添加逻辑以确定用户是否已登录。
我还想指出,当用户登录时,在侧边栏中渲染的注销按钮。这里的重要步骤是确保key=对于每个页面都有一个唯一的名称。保持简单,使用你的应用程序名称并将页面名称附加到键的值上。这对于登录小部件也是如此。
为小部件提供的唯一键以避免重复的 WidgetID 错误。
# Authentication logictry:authenticator.login(location="main",key="login-demo-app-home")exceptLoginErrorase:st.error(e)ifst.session_state["authentication_status"]:authenticator.logout(location="sidebar",key="logout-demo-app-home")elifst.session_state["authentication_status"]isFalse:st.error("Username/password is incorrect")elifst.session_state["authentication_status"]isNone:st.warning("Please enter your username and password")让我们看看登录并保存上述信息到会话状态后,会话状态看起来像什么。我们立即注意到一些突出的事项。有一个名为logout-demo-app-home的键,它表示注销按钮的状态。还有我们的认证器对象以及配置存储。此外,我们还可以访问有关用户的信息,如用户名、电子邮件、姓名和角色。所有这些都非常有助于个性化你的应用程序!
https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/ab12034932b9fc9a729ea1214bb15e6c.png
图片由作者提供
设置所有附加页面
现在是时候看看如何让你的应用程序中的后续页面无缝工作。在名为pages的文件夹中创建一个新文件,并适当地命名它以反映你的功能。我会保持简单,将其命名为Page_1.py。让我们从导入和基本的 Streamlit 代码开始。请注意,我们不需要直接导入任何认证器包,因为我们只将使用会话状态的信息。
importstreamlitasstimportyaml st.set_page_config(page_title="Page 1")st.title("Page 1")在渲染任何页面信息之前,我们可以检查用户是否已认证。在会话状态中有一个顶级键,名为authentication_status,它是一个boolean类型的值。我们可以简单地检查它是否为true,然后从会话状态中检索认证器对象。
开发者给出的一个建议是,对于每个页面,你需要调用登录小部件,但这次不要渲染它。此外,你还将提供一个新的、唯一的键值,这有助于在导航页面时避免会话冲突。
ifst.session_state.get("authentication_status"):authenticator=st.session_state.get("authenticator")authenticator.logout(location="sidebar",key="logout-demo-app-page-1")authenticator.login(location="unrendered",key="authenticator-page-1")# Put the main code and logic for your page here.st.success("You are logged in!")elifst.session_state=={}orst.session_state["authentication_status"]isNone:st.warning("Please use the button below to navigate to Home and log in.")st.page_link("Home.py",label="Home",icon="🏠 ")st.stop()如果用户未认证,让他们返回到主页并登录。这段代码可以很容易地重复在每一个页面上。只需记住为所有键提供唯一的值。
https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/6a0c21141d51f175d9879a50e2eaa8d3.png
图片由作者提供
奖励:管理员角色和工具
开发者最近将角色的概念添加到应用程序中。这些以一组字符串的简单配置形式出现,实际上可以是任何你想要的内容。用于分离功能的东西。这里有一个用户,它附有三个角色。
credentials:usernames:brian:email:[[email protected]](/cdn-cgi/l/email-protection)failed_login_attempts:0first_name:Brian last_name:Roepke logged_in:false password:<<hashed-pw>>roles:-admin-editor-viewer这的好处在于,角色将显示在会话状态的最高级别,并且该用户的角色将以一个简单的值列表的形式返回。
https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/72e50d18f8912272ecf8d1cdf31224c4.png
图片由作者提供
基于此,我们可以编写一些简单的代码来检查会话状态中的角色值,然后随后检查管理员是否在可用的值中。就这么简单!
try:user_roles=st.session_state.get("roles",[])or[]if"admin"inuser_roles:st.subheader("Admin Tools")# Implement anything you like here that is Admin onlyexceptExceptionase:st.error(f"An error occurred:{e}")在我的应用中,我选择创建一个简单的实用工具,允许我下载配置数据作为文件,以防它被更新,并且如果需要检查会话状态,还可以打印出来。
https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/1d584678c3a6c07276c8618d1f152109.png
图片由作者提供
这里再次提供了您入门应用的完整代码。
结论
总之,将 Streamlit Authenticator 集成到您的多页 Streamlit 应用中可以简化用户管理的添加。通过遵循本指南中概述的步骤,您可以有效地管理不同页面之间的身份验证,确保用户体验的流畅性。角色的添加还允许进行定制访问和功能,使您的应用更加健壮和多功能。有了这些工具和技术,您就为构建多用户友好的应用做好了充分准备。祝您编码愉快!
如果您喜欢阅读这样的故事,并想支持我作为作家,请考虑注册成为 Medium 会员。每月仅需 5 美元,即可无限访问数千篇文章。如果您使用我的链接注册,我将获得一小笔佣金,而无需额外费用。