集成FusionAuth与Django-Rest-Framework:如何复用Access Token?
FusionAuth与Django-Rest-Framework + React集成:复用FusionAuth Token的实现方案
现有流程与问题
我目前正在把FusionAuth和Django-Rest-Framework(搭配React前端)集成,采用授权码授权流程:
- React前端跳转到FusionAuth登录页,登录完成后携带
authorization_code重定向回前端 - 前端将该code传给Django后端,后端用它换取FusionAuth的
access_token,再通过token拉取用户信息(含唯一ID) - 后端根据用户ID创建/获取本地Django用户,随后用knox生成本地token返回给前端做后续认证
现有伪代码如下:
from fusionauth.fusionauth_client import FusionAuthClient client = FusionAuthClient(FA_API_KEY, FA_URL) def authenticate(request): authorization_code = request.data["code"] fa_token_response = client.exchange_o_auth_code_for_access_token() fa_user_response = client.retrieve_user(user_id=fa_token_response["userId"]) user, created = UserModel.objects.get_or_create( fa_id=fa_token_response["userId"], defaults={ "username": fa_user_response["username"], "email": fa_user_response["email"], }, ) token = generate_token(user) # 想替换成直接用FusionAuth的token return Response( { "token": token, "user_id": user.id, }, status=status.HTTP_200_OK, )
现在想直接复用FusionAuth提供的access_token和refresh_token,以此共享过期时间、简化流程,但不清楚具体实现方式:
- 是否可以直接复用FusionAuth的token?
- 若每次请求都验证token,会不会存在效率问题?
- 有没有现成的第三方库可以解决这个问题?
解决方案建议
1. 直接复用FusionAuth的Token
完全可以直接把FusionAuth返回的access_token、refresh_token以及过期时间一起返回给前端,前端后续请求时将access_token放在请求头(如Authorization: Bearer {token})中传给DRF后端即可。
2. 实现DRF认证后端验证Token
需要编写自定义的DRF认证后端,每次请求时验证FusionAuth的access_token有效性:
- 核心逻辑是调用FusionAuth的
introspect tokenAPI(若FusionAuth Token为JWT格式,也可直接本地验证) - 关于效率问题:可通过缓存验证结果解决,比如用Redis缓存已验证的有效Token,缓存过期时间与FusionAuth Token的过期时间一致,避免每次请求都调用FusionAuth API
示例认证后端伪代码:
from rest_framework.authentication import BaseAuthentication from rest_framework.exceptions import AuthenticationFailed from fusionauth.fusionauth_client import FusionAuthClient from django.core.cache import cache client = FusionAuthClient(FA_API_KEY, FA_URL) class FusionAuthTokenAuthentication(BaseAuthentication): def authenticate(self, request): auth_header = request.headers.get('Authorization') if not auth_header or not auth_header.startswith('Bearer '): return None token = auth_header.split(' ')[1] # 优先查询缓存 cached_user_id = cache.get(f'fa_token_{token}') if cached_user_id: try: user = UserModel.objects.get(fa_id=cached_user_id) return (user, None) except UserModel.DoesNotExist: raise AuthenticationFailed('用户不存在') # 缓存未命中,调用FusionAuth验证Token response = client.introspect_o_auth_token(token) if not response.was_successful(): raise AuthenticationFailed('Token无效或已过期') fa_user_id = response.success_response['userId'] # 缓存验证结果,提前60秒过期避免时间差问题 cache.set(f'fa_token_{token}', fa_user_id, timeout=response.success_response['expires_in'] - 60) user, _ = UserModel.objects.get_or_create(fa_id=fa_user_id) return (user, None)
随后在DRF配置中启用该认证后端:
REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': [ 'your_app.authentication.FusionAuthTokenAuthentication', # 其他认证方式... ] }
3. 第三方库参考
- 若需要简化OAuth2认证流程,可尝试
django-oauth-toolkit,适配FusionAuth配置后可快速实现Token验证逻辑 - 若FusionAuth使用JWT格式的Token,推荐用
djangorestframework-simplejwt做本地验证,无需每次调用FusionAuth API,效率更高
内容的提问来源于stack exchange,提问作者trubliphone
相关产品推荐
相关产品推荐

