Flet框架中Discord OAuth登录的on_login函数未执行问题排查
我完全懂你这种挫败感——明明登录授权的流程走通了,跳转也成功了,可核心的on_login函数就是纹丝不动。咱们一步步拆解问题,从配置到代码,把这个坑填上。
一、先确认重定向URL的“精确匹配”
Discord对OAuth重定向URL的要求是完全精确匹配,差一个字符都不行。你代码里的redirect_url是http://localhost:2000/api/auth/discord/redirect,一定要去Discord开发者后台检查:
- 端口是不是2000?
- 路径是不是完全一致(包括
/api/auth/discord/redirect的每一个斜杠)? - 协议是http还是https?你用的是http,后台也必须是http,不能混着来
哪怕多一个末尾的斜杠(比如写成.../redirect/),Discord的回调都不会被Flet正确识别,自然触发不了on_login。
二、检查Flet Web模式的路由兼容性
Flet在Web浏览器模式下,对较深的路由路径(比如你用的/api/auth/discord/redirect)可能存在处理盲区。你可以先简化重定向路径做测试:
- 把代码里的
redirect_url改成http://localhost:2000/discord-redirect - 同步更新Discord后台的重定向URL配置
- 重新运行代码测试
如果简化路径后on_login能触发,说明之前的深路径和Flet的默认路由机制冲突了,后续可以再调整路径,或者用Flet的路由API手动处理回调。
三、代码逻辑的小细节优化
1. 手动触发页面更新
Flet的page.add()理论上会自动更新页面,但在OAuth回调这种异步场景下,有时候需要手动调用page.update()来确保UI更新。你可以修改on_login函数:
def on_login(e): print('on_login called', flush=True) # 先把笔误的on_logi改回来哦 page.add(flet.Text('on_login called')) if e.error: page.add(ElevatedButton(f"Login error: {e.error}")) else: page.add(ElevatedButton(f"User ID: {page.auth.user.id}")) page.add(ElevatedButton(f"Access token: {page.auth.token.access_token}")) page.update() # 手动强制更新页面
2. 确认on_login的绑定时机
虽然你的代码顺序没问题,但可以尝试把page.on_login = on_login的位置提前,比如在定义完on_login函数后立刻绑定,避免后续代码意外覆盖这个回调:
def on_login(e): # ... 你的函数逻辑 ... # 定义完on_login后立刻绑定 page.on_login = on_login # 再定义login_click和添加按钮 def login_click(e): page.login(provider) print('hello') page.add(ElevatedButton("Login with Discord", on_click=login_click))
3. 检查服务器端的控制台输出
你在on_login里加了flush=True,这个输出是打印在运行Flet的服务器控制台,而不是浏览器的开发者工具控制台。一定要去看启动Flet的那个终端窗口,有没有on_login called的输出:
- 如果有输出:说明on_login其实被触发了,只是页面没更新,这时候加
page.update()就能解决UI问题 - 如果没有输出:说明回调根本没传到Flet的auth处理逻辑,回到前面的重定向URL和路由排查
四、升级Flet到最新版本
旧版本的Flet在Web模式下的OAuth回调处理可能存在bug,建议你先升级到最新版:
pip install --upgrade flet
升级后再测试,很多奇怪的回调问题都会被新版本修复。
五、简化测试场景
如果上面的方法都没用,咱们把代码简化到最基础的版本,排除干扰:
import os import flet from flet import Page, ElevatedButton, Text from flet.auth import OAuthProvider def main(page: Page): provider = OAuthProvider( client_id=os.getenv("DISCORD_CLIENT_ID"), client_secret=os.getenv("DISCORD_CLIENT_SECRET"), authorization_endpoint="https://discord.com/oauth2/authorize", token_endpoint="https://discord.com/api/oauth2/token", scopes=['identify'], # 只保留最必要的权限 redirect_url="http://localhost:2000/discord-redirect", ) def on_login(e): print("ON_LOGIN TRIGGERED!", flush=True) if e.error: page.add(Text(f"Error: {e.error}")) else: page.add(Text(f"Logged in as {page.auth.user.id}")) page.update() def login_click(e): page.login(provider) page.on_login = on_login page.add(ElevatedButton("Login with Discord", on_click=login_click)) flet.app(main, port=2000, view=flet.WEB_BROWSER)
同时更新Discord后台的重定向URL为http://localhost:2000/discord-redirect,测试这个极简版本能不能触发on_login。如果这个版本能行,再逐步加回你需要的scope和功能。
内容来源于stack exchange

