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
- Auth0
当然,您可以配置一个通用的OAuth提供程序,并提供授权、令牌和用户信息端点。
与github的集成
为了将Flet认证与GitHub集成,首先注册GitHub OAuth应用程序(Profile settings → Developer settings → OAuth Apps)。
Authorization callback URL 必须设置成以下格式:
{application-url}/api/oauth/redirect
在OAuth应用程序页面上点击“Generate a new client secret”按钮。复制“Client ID”和“Client secret”的值到一个安全的地方-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应用程序:一个新的弹出窗口(确保弹出窗口拦截器是关闭的)。
- 移动应用程序:应用内的网页浏览器。
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集成登录,登出示例:
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集成保存登录信息示例
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)
版权声明:内容来源于互联网和用户投稿 如有侵权请联系删除