Flet简明中文教程(二十六)内置身份认证

发布一下 0 0

Flet应用程序支持使用第三方身份认证,如GitHub, Google, Azure, Auth0, LinkedIn等支持OAuth 2.0 协议的应用。

Flet身份认证的特性:

  • 支持Flet桌面,网页和移动应用程序。
  • 支持应用程序中使用多个身份验证提供者。
  • 内置的OAuth提供程序,可自动获取用户详细信息(GitHub, Google, Azure, Auth0)。
  • 支持组信息获取。
  • 支持自动刷新令牌。
  • 支持保存过的令牌登录。
  • 支持定制OAuth提供者。

登录流程

  • 使用Client ID, Client secret, Redirect URL配置OAuth provider(内置或通用),。
  • 调用page.login(provider)来启动OAuth 交互流程。
  • 用户被重定向到OAuth提供者网站。
  • 在OAuth提供者网站上,用户登录并授权Flet应用的请求。
  • 提供者网站重定向到Flet回调URL获取到授权Code。
  • Flet带上授权Code,Client ID, Client secret到提供者网站获取access_token;后调用on_login事件处理程序。
  • Flet应用程序从page.auth.token属性中检索API令牌,从page.auth.user中检索用户详细信息。

配置OAuth provider

Flet有一些内置的OAuth providers:

  • GitHub
  • Azure
  • Google
  • Auth0

当然,您可以配置一个通用的OAuth提供程序,并提供授权、令牌和用户信息端点。

与github的集成

为了将Flet认证与GitHub集成,首先注册GitHub OAuth应用程序(Profile settingsDeveloper settingsOAuth Apps)。

Authorization callback URL 必须设置成以下格式:

{application-url}/api/oauth/redirect
Flet简明中文教程(二十六)内置身份认证

在OAuth应用程序页面上点击“Generate a new client secret”按钮。复制“Client ID”和“Client secret”的值到一个安全的地方-Flet应用程序需要它们。

Flet简明中文教程(二十六)内置身份认证

登录示例

import osimport fletfrom flet import ElevatedButton, Pagefrom flet.auth.providers.github_oauth_provider import GitHubOAuthProviderdef main(page: Page):    provider = GitHubOAuthProvider(        client_id=os.getenv("GITHUB_CLIENT_ID"),        client_secret=os.getenv("GITHUB_CLIENT_SECRET"),        redirect_url="http://localhost:8550/api/oauth/redirect",    )    def login_click(e):        page.login(provider)    def on_login(e):        print("Access token:", page.auth.token.access_token)        print("User ID:", page.auth.user.id)    page.on_login = on_login    page.add(ElevatedButton("Login with GitHub", on_click=login_click))flet.app(target=main, port=8550, view=flet.WEB_BROWSER)

运行程序前,需先设置环境变量:

$ export GITHUB_CLIENT_ID="<client_id>"$ export GITHUB_CLIENT_SECRET="<client_secret>"

运行程序,点击“Login with GitHub”按钮。GitHub授权应用页面将出现在:

  • 桌面应用程序:一个新的浏览器窗口或选项卡。
  • Web应用程序:一个新的弹出窗口(确保弹出窗口拦截器是关闭的)。
  • 移动应用程序:应用内的网页浏览器。
Flet简明中文教程(二十六)内置身份认证

Redirect URL

我们使用http://localhost:8550/api/oauth/redirect作为GitHub OAuth App跳转url,注意使用的端口是8550,所以需要以下方式调用程序

flet.app(target=main, port=8550)

Scope

通常OAuth提供程序允许应用程序请求一个或多个scopes,以限制应用程序对用户帐户的访问。

默认情况下,内置的Flet提供程序会请求访问用户配置文件的scope,但是你可以在登录方法中请求其他scopes,比如的public_repo:

page.login(    provider,    scope=["public_repo"])

page.login() 参数

  • fetch_user (bool) -是否获取用户信息,存放在 page.auth.user。
  • fetch_groups (bool) - 是否获取组信息,存放在page.auth.user.groups。
  • scope - 请求权限列表。
  • saved_token - 保存的access_token,下次登录直接使用。
  • on_open_authorization_url -授权url打开方法。
  • complete_page_html - 授权后跳转的页面内容
  • redirect_to_page (bool) - 当授权页面在原始页面打开时使用。

page.login() 返回值

返回的是Authorization类实例,具有以下属性:

  • token
  • user
  • provider

最后一次登录的信息,保存在page.auth

授权结果

无论授权成功还是失败,都会调用page.on_login事件处理程序

事件处理程序参数e是LoginEvent类的一个实例,具有以下属性:

error (str)—OAuth错误。

error_description (str) - OAuth错误描述。

成功时,error是个空字符串

获取用户信息

如果page.login()方法被调用时,fetch_user=True(默认),用户信息将被保存在page.auth.user中。

Flet内置的OAuth提供程序都支持user.id属性:用户唯一标识符(该值取决于认证网站提供者,可以是一个数字,Guid或电子邮件)。

其余的用户属性取决于认证网站提供程序,可以通过索引访问。例如,GitHub用户的一些属性:

print("Name:", page.auth.user["name"])print("Login:", page.auth.user["login"])print("Email:", page.auth.user["email"])

登出

调用page.logout()重置page.auth,并触发on_logout事件处理程序。

例如:

def logout_button_click(e):    page.logout()def on_logout(e):		pass    page.on_logout = on_logout


GitHub集成登录,登出示例:

Flet简明中文教程(二十六)内置身份认证

import osfrom telnetlib import LOGOUTimport fletfrom flet import ElevatedButton, Page,LoginEvent,Text,Row,Reffrom flet.auth.providers.github_oauth_provider import GitHubOAuthProviderdef main(page: Page):    provider = GitHubOAuthProvider(        client_id=os.getenv("GITHUB_CLIENT_ID"),        client_secret=os.getenv("GITHUB_CLIENT_SECRET"),        redirect_url="http://localhost:8550/api/oauth/redirect",    )    login_ui = Ref[Row]()    logout_ui = Ref[ElevatedButton]()    login_info_text = Ref[Text]()    def login_click(e):        page.login(provider)           def logout_click(e):        page.logout()           def on_login(e:LoginEvent):                show_login_status()    def on_logout(e):        show_login_status()    def show_login_status():        login_ui.current.visible = page.auth is not None        logout_ui.current.visible = page.auth is  None        if page.auth is not None:            login_info_text.current.value = f"Welcome {page.auth.user['login']}"        page.update()    page.on_login = on_login    page.on_logout = on_logout    page.add(ElevatedButton("Login with GitHub", on_click=login_click,ref=logout_ui))    page.add(        Row(            [                Text(ref=login_info_text),                ElevatedButton("退出",on_click=logout_click)            ],            ref=login_ui        )    )    show_login_status()flet.app(target=main, port=8550,view=flet.WEB_BROWSER)

保存登录信息

要实现持久登录(登录页面上的“记住我”复选框),可以在客户端存储认证令牌,并在下次用户重新打开Flet应用程序时使用它登录。

序列话登录token

jt = page.auth.token.to_json()

加密序列话后的token

import osfrom flet.security import encrypt, decryptsecret_key = os.getenv("MY_APP_SECRET_KEY")# returns base64-encoded stringejt = encrypt(jt, secret_key)

运行程序前,先设置环境变量

$ export MY_APP_SECRET_KEY="<secret>"

客户端存储加密后的token

page.client_storage.set("myapp.auth_token", ejt)

下次用户打开应用程序时,可以从客户端存储读取加密的令牌,如果它存在,解密它并在page.login()方法中使用:

ejt = page.client_storage.get("myapp.auth_token")if ejt:    jt = decrypt(ejt, secret_key)    page.login(provider, saved_token=jt)

Github集成保存登录信息示例

Flet简明中文教程(二十六)内置身份认证

import osimport fletfrom flet import ElevatedButton, Page,LoginEvent,Text,Row,Reffrom flet.auth.providers.github_oauth_provider import GitHubOAuthProviderfrom flet.security import encrypt,decryptdef main(page: Page):    provider = GitHubOAuthProvider(        client_id=os.getenv("GITHUB_CLIENT_ID"),        client_secret=os.getenv("GITHUB_CLIENT_SECRET"),        redirect_url="http://localhost:8550/api/oauth/redirect",    )    secret_key = os.getenv("MY_APP_SECRET_KEY")    login_ui = Ref[Row]()    logout_ui = Ref[ElevatedButton]()    login_info_text = Ref[Text]()    def login_click(e):        jt = page.client_storage.get("myapp.auth_token")        ejt = None        if jt:                        ejt = decrypt(jt,secret_key)        print(f"token: {ejt}")        page.login(provider,saved_token=ejt)           def logout_click(e):        page.logout()           def on_login(e:LoginEvent):        if not e.error:               jt = page.auth.token.to_json()                       ejt = encrypt(jt,secret_key)            page.client_storage.set("myapp.auth_token",ejt)            show_login_status()    def on_logout(e):        page.client_storage.remove("myapp.auth_token")        show_login_status()    def show_login_status():        login_ui.current.visible = page.auth is not None        logout_ui.current.visible = page.auth is  None        if page.auth is not None:            login_info_text.current.value = f"Welcome {page.auth.user['login']}"        page.update()    page.on_login = on_login    page.on_logout = on_logout    page.add(ElevatedButton("Login with GitHub", on_click=login_click,ref=logout_ui))    page.add(        Row(            [                Text(ref=login_info_text),                ElevatedButton("退出",on_click=logout_click)            ],            ref=login_ui        )    )    show_login_status()flet.app(target=main, port=8550,view=flet.WEB_BROWSER)

版权声明:内容来源于互联网和用户投稿 如有侵权请联系删除

本文地址:http://0561fc.cn/178803.html