Django REST Framework JWT返回匿名用户问题(Angular 5)
首先,咱们先拆解这个问题:报错的直接原因是你在自定义权限类里用字典索引方式request.user['issuitssuperuser']访问匿名用户(AnonymousUser)的属性,但Django的AnonymousUser是类实例,不是字典,不支持__getitem__方法,所以抛出了TypeError。不过更深层的问题是——明明前端已经在请求头里带了JWT Token,为什么后端的request.user还是AnonymousUser?这说明你的后端JWT认证流程没有正确生效,导致用户身份没被识别。
接下来分步骤解决:
1. 先修复权限类的属性访问方式
不管认证问题是否解决,这个写法本身就不规范,先改成Django用户对象的标准属性访问方式:
class Issuitssuperuser(BasePermission): def has_permission(self, request, view): # 先处理跨域预检的OPTIONS请求(后面会说原因) if request.method == 'OPTIONS': return True # 先判断用户是否已认证,避免后续访问属性报错 if not request.user.is_authenticated: return False # 用点语法访问用户属性 return request.user.issuitssuperuser
2. 排查后端JWT认证未生效的原因
2.1 检查DRF的认证类配置
确保Django REST Framework已经把JWT认证类加入到默认认证列表里,比如在settings.py中:
REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': [ 'rest_framework_jwt.authentication.JSONWebTokenAuthentication', # 如果你还需要其他认证方式,比如session认证,可以保留 'rest_framework.authentication.SessionAuthentication', ], # 其他DRF配置... }
如果用的是第三方JWT库(比如djangorestframework-simplejwt),要替换成对应的认证类,比如rest_framework_simplejwt.authentication.JWTAuthentication。
2.2 验证请求头格式是否匹配
前端Interceptor里设置的是Authorization: 'JWT ' + token,要确认后端JWT库是否期望这个前缀:
- 比如
rest_framework_jwt默认支持JWT前缀; - 如果你用的是
simplejwt,默认期望的是Bearer前缀,这时候需要前端改成Authorization: 'Bearer ' + token,或者在后端配置里修改前缀。
2.3 测试Token的有效性
用Postman直接发请求测试:手动添加Authorization头(比如JWT your_valid_token),调用需要权限的API,查看响应中是否返回用户信息,同时在后端打印request.user,确认是否是已认证的用户对象,而不是AnonymousUser。如果这里还是匿名用户,说明Token本身无效(比如过期、签名错误、生成Token时的密钥和后端不一致)。
2.4 处理跨域预检请求
从报错日志里看到是OPTIONS /api/user/suits/请求触发的500错误,这是浏览器的跨域预检请求。浏览器在发送跨域的非简单请求(比如带自定义头的请求)前,会自动发送OPTIONS请求,这个请求默认不会携带Authorization头,所以后端如果对OPTIONS请求也做权限验证,就会触发匿名用户的报错。
解决办法:
- 如果你用
django-cors-headers库,确保配置了允许Authorization头:CORS_ALLOW_HEADERS = [ 'authorization', 'content-type', # 其他需要的头... ] - 在权限类里先判断请求方法,如果是OPTIONS,直接返回允许(就像第一步里的代码那样);
- 确保后端的CORS配置允许预检请求通过,不会被拦截。
3. 额外检查:前端Interceptor是否对所有请求生效
虽然你说Token能正确添加到请求头,但可以再确认下:
- Interceptor是否在Angular的
providers里正确注册了? - 是否有某些请求被排除在了Interceptor之外?比如域名白名单之类的配置?
按照上面的步骤排查,应该能解决你的问题——先修复权限类的写法,再确保后端JWT认证流程正常,最后处理跨域预检的问题。
内容的提问来源于stack exchange,提问作者user9487981

