Django auth_adfs配置求助:内外用户鉴权冲突及#EXT#错误
解决Django + django_auth_adfs 内外用户认证兼容方案
核心思路是放弃单一的USERNAME_CLAIM配置,自定义用户名解析逻辑,同时调整Django用户模型的验证规则,兼容内部用户和带#EXT#后缀的外部用户令牌。
1. 自定义用户名解析函数
在项目中创建工具模块(如adfs_utils.py),编写从JWT令牌claims中提取合法用户名的逻辑:
def get_username_from_claims(claims): # 优先处理upn,移除外部用户的#EXT#后缀 if 'upn' in claims: upn = claims['upn'] return upn.replace('#EXT#', '') if '#EXT#' in upn else upn # 降级使用email,兼容部分内部用户场景 elif 'email' in claims: return claims['email'] # 兜底用sub(Azure AD唯一用户标识),避免认证失败 return claims['sub']
在settings.py中配置django_auth_adfs使用该函数:
AUTH_ADFS = { # 保留原有其他配置(如CLIENT_ID、TENANT_ID等) 'USERNAME_CLAIM': None, # 禁用默认单一claim解析 'CUSTOM_USERNAME_CLAIM_PROVIDER': 'your_project.adfs_utils.get_username_from_claims', }
2. 调整Django用户模型的用户名验证规则
默认Django用户名不允许包含@、#等字符,需修改用户模型适配:
方案A:使用自定义用户模型
在应用的models.py中定义自定义用户模型:
from django.contrib.auth.models import AbstractUser from django.db import models class CustomUser(AbstractUser): username = models.CharField( max_length=255, unique=True, help_text="支持包含@、.等字符的用户名", validators=[], # 清空默认用户名验证器,允许更多字符 )
在settings.py指定自定义用户模型:
AUTH_USER_MODEL = 'your_app.CustomUser'
注意:若已有用户数据,需执行数据迁移命令
python manage.py makemigrations和python manage.py migrate,确保数据兼容。
方案B:修改默认用户模型的验证器(仅临时场景)
若不想替换用户模型,可通过修改全局验证器实现:
# 在项目初始化文件(如apps.py)中修改 from django.contrib.auth.validators import UnicodeUsernameValidator UnicodeUsernameValidator.regex = r'^[\w.@+-]+$'
3. 确认Azure AD应用注册配置
- 进入Azure门户的应用注册页面,在「令牌配置」中添加
upn和email作为可选声明并启用 - 确保应用的「支持的账户类型」设置为「任何组织目录中的账户和个人Microsoft账户」(按需调整,若仅需企业外部用户可选择对应选项)
4. 验证测试
- 分别使用内部域用户和外部注册用户登录系统,检查用户对象的
username字段是否正确解析 - 测试后端API接口,确认两类用户均能正常访问,无401或500错误
内容的提问来源于stack exchange,提问作者Georgios
相关产品推荐
相关产品推荐

