drf-social-oauth2中JWT自定义声明及request.user匿名问题
你遇到的核心问题是在重写TokenView.create_token_response时,request.user仍为AnonymousUser——这是因为该方法执行阶段,认证流程尚未将已验证的用户关联到当前request对象上。以下是两种可行的解决方案:
方案一:从原始JWT中提取用户ID并查询用户
原始生成的JWT令牌中已经包含用户身份标识(drf-social-oauth2默认是user_id字段),你可以解码原始令牌获取用户ID,再查询用户模型拿到所需信息:
from drf_social_oauth2.views import TokenView import json from jose import jwt from django.conf import settings from django.contrib.auth import get_user_model User = get_user_model() class CustomTokenView(TokenView): def create_token_response(self, request): response_data = super().create_token_response(request) url, headers, body, status = response_data # 仅处理成功获取令牌的情况 if status == 200: token_data = json.loads(body) access_token = token_data.get("access_token") # 解码原始JWT,关闭过期验证(因为刚生成的令牌不会过期) decoded_token = jwt.decode( access_token, settings.SECRET_KEY, algorithms=["HS256"], options={"verify_exp": False} ) # 从解码结果中获取用户ID user_id = decoded_token.get("user_id") user = User.objects.get(id=user_id) # 添加自定义声明 decoded_token["custom_claim"] = "custom_value" decoded_token["username"] = user.username decoded_token["email"] = user.email # 重新编码JWT updated_access_token = jwt.encode( decoded_token, settings.SECRET_KEY, algorithm="HS256" ) token_data["access_token"] = updated_access_token modified_body = json.dumps(token_data) return url, headers, modified_body, status return response_data
方案二:重写JWT Payload生成器(更优雅)
drf-social-oauth2支持通过配置自定义JWT Payload生成函数,这是官方推荐的扩展方式,无需重写视图:
- 在项目中创建工具文件(比如
account/utils.py),添加自定义Payload处理函数:
from drf_social_oauth2.utils import default_jwt_payload_handler def custom_jwt_payload_handler(user, issuer=None, audience=None, scope=None): # 先调用默认生成器获取基础payload payload = default_jwt_payload_handler(user, issuer, audience, scope) # 添加自定义声明 payload["custom_claim"] = "custom_value" payload["username"] = user.username payload["email"] = user.email return payload
- 在
settings.py中配置该函数:
# drf-social-oauth2 JWT配置 ACTIVATE_JWT = True JWT_PAYLOAD_HANDLER = "account.utils.custom_jwt_payload_handler"
这种方式直接在JWT生成阶段注入自定义声明,能直接拿到已验证的用户对象,避免了手动查询用户的步骤,代码更简洁易维护。
内容的提问来源于stack exchange,提问作者Ashutosh Chapagain
相关产品推荐
相关产品推荐

