Django REST验证Azure JWT令牌无法提取请求头令牌问题
Django REST 框架下 Azure AD JWT 令牌验证实现方案
一、令牌传入的正确写法
官方给出的示例是脱离Web服务上下文的最小功能演示代码,本身不处理HTTP请求逻辑,所以识别不到request对象是正常的。你只需要在Django的视图/中间件/认证类这些能拿到请求对象的位置,先处理请求头再传值即可。
注意前端按OAuth2.0规范传的Authorization头格式为Bearer <实际JWT字符串>,不能直接把整个头的值传入校验方法,必须先剥离Bearer 前缀。
可参考下面的视图实现:
from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import status from azure_ad_verify_token import verify_jwt # 配置建议统一放到settings.py维护,不要硬编码 AZURE_AD_APP_ID = "你的Azure应用客户端ID" AZURE_AD_ISSUER = "你的Azure租户令牌签发地址" AZURE_AD_JWKS_URI = "你的Azure JWKS公钥发现地址" class AzureAuthProtectedView(APIView): def get(self, request): # 安全提取授权头,避免KeyError auth_header = request.headers.get("Authorization", "") if not auth_header.startswith("Bearer "): return Response( {"detail": "授权头格式非法,需遵循Bearer <token>格式"}, status=status.HTTP_401_UNAUTHORIZED ) # 截取有效令牌部分 token = auth_header.split(maxsplit=1)[1].strip() try: # 传入处理后的令牌完成校验 token_payload = verify_jwt( token=token, valid_audiences=[AZURE_AD_APP_ID], issuer=AZURE_AD_ISSUER, jwks_uri=AZURE_AD_JWKS_URI, verify=True, ) except Exception as e: return Response( {"detail": f"令牌校验失败:{str(e)}"}, status=status.HTTP_401_UNAUTHORIZED ) # 校验通过后可根据payload里的用户信息做登录、权限判断逻辑 return Response({"user_claims": token_payload}, status=status.HTTP_200_OK)
二、实现正确性说明与易遗漏配置点
- 整体流程是正确的:React前端通过MSAL完成授权拿到access token、请求时携带Authorization头、后端提取令牌校验,完全符合OpenID Connect的Bearer令牌认证规范。
- 几个容易踩的遗漏点:
- 必须处理Bearer前缀:直接把整个Authorization头的值传入校验方法,会因为令牌格式不合法直接报错,这是最常见的问题。
- 三个核心配置必须和Azure门户的应用注册配置完全匹配:
valid_audiences默认填应用客户端ID即可,如果你的服务暴露了自定义API scope,需要把对应的API应用ID也加入列表issuer地址要和租户类型、令牌版本匹配,B2C租户、普通全球版租户、多租户应用的签发地址格式有差异,填错会直接校验失败jwks_uri要和你使用的用户流(B2C场景)、令牌版本(v1.0/v2.0)对应,不同端点的公钥不通用
- 必须加异常捕获:令牌过期、签名篡改、aud/iss不匹配时
verify_jwt会直接抛出异常,不做捕获的话接口会返回500错误,而不是正确的401状态码。 - 生产环境建议把校验逻辑封装成DRF自定义认证类,全局配置后不需要在每个视图里重复写提取、校验逻辑,减少冗余代码。
- JWKS公钥默认会有缓存,不用每次请求都拉取,azure-ad-verify-token库本身已经做了这层处理,不需要额外开发。
三、Python生态常用的JWT/Azure AD验证库推荐
PyJWT:生态最通用的JWT基础处理库,灵活度最高,需要自己实现JWKS拉取、公钥缓存、声明校验逻辑,适合有自定义校验规则的场景。msal:微软官方推出的Python身份认证库,除了JWT校验,还支持服务端令牌获取、分布式令牌缓存、证书认证等全流程能力,和Azure生态适配度最高。authlib:兼容OAuth2.0、OpenID Connect全协议的认证库,内置JWT校验、JWKS自动拉取缓存能力,同时支持多家身份提供商,适合做多源登录的系统。django-auth-adfs:专门针对Django生态封装的Azure AD/AD FS集成库,内置DRF认证后端、用户自动映射、组权限同步等能力,Django技术栈使用可以大幅减少重复代码。
内容的提问来源于stack exchange,提问作者Elliot13
相关产品推荐
相关产品推荐

