You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django API:登录生成Token但Profile视图提示未认证及AnonymousUser无email问题

问题原因
  1. 重定向丢失认证信息:Login视图登录成功后执行重定向,你设置的request.META['HTTP_AUTHORIZATION']仅对当前POST请求有效,重定向后的GET请求是全新请求,不会携带Token头,导致Profile视图无法识别已认证用户。
  2. 浏览器未自动携带Token:Postman是手动添加了Token请求头才正常,而浏览器端请求Profile时,没有在请求头中携带Token,因此request.user为AnonymousUser,访问user.email就会触发'AnonymousUser' object has no attribute 'email'错误。
解决办法

1. 调整Login视图的返回逻辑

去掉重定向,直接返回Token给前端,让前端存储并在后续请求中携带:

class LoginView(APIView):
    permission_classes = (permissions.AllowAny,)
    # 移除不必要的TokenAuthentication,登录请求不需要携带Token
    # authentication_classes = (TokenAuthentication,)

    def post(self, request):
        username = request.data.get('username')
        password = request.data.get('password')

        user = authenticate(username=username, password=password)
        if user is not None:
            token, created = Token.objects.get_or_create(user=user)
            # 返回Token和用户信息,而非重定向
            return Response({"token": token.key, "username": user.username})
        else:
            return Response({'error': 'Invalid credentials'}, status=400)

2. 前端请求Profile时携带Token

前端拿到Token后,存储到本地(比如localStorage),每次请求Profile时在请求头中添加Authorization字段:

// 登录成功后存储Token
fetch('/login/', {
  method: 'POST',
  headers: {'Content-Type': 'application/json'},
  body: JSON.stringify({username: 'your-username', password: 'your-password'})
})
.then(res => res.json())
.then(data => {
  localStorage.setItem('authToken', data.token);
});

// 请求Profile时携带Token
fetch('/profile/', {
  headers: {
    'Authorization': 'Token ' + localStorage.getItem('authToken')
  }
})
.then(res => res.json())
.then(data => console.log(data));

3. 优化Profile视图的权限控制

将Profile视图的权限改为IsAuthenticated,让DRF自动拦截未认证请求,避免手动判断的冗余:

from rest_framework.permissions import IsAuthenticated

class ProfileView(APIView):
    permission_classes = (IsAuthenticated,)

    def get(self, request):
        # 已认证用户直接返回信息,无需判断is_authenticated
        return Response({'username': request.user.username, 'email': request.user.email})

可选:改用Session认证(服务端渲染场景)

如果你的项目是服务端渲染(比如用Django模板),不想用Token,可以改用Session认证:

  • 移除Login视图中的Token相关代码,保留login(request, user)
  • 确保settings.py中启用SessionAuthentication(默认已启用)
  • Profile视图无需手动处理Token,request.user会自动通过Session识别:
class LoginView(APIView):
    permission_classes = (permissions.AllowAny,)

    def post(self, request):
        username = request.data.get('username')
        password = request.data.get('password')
        user = authenticate(username=username, password=password)
        if user is not None:
            login(request, user)
            return redirect('myprofile:profile')
        else:
            return Response({'error': 'Invalid credentials'}, status=400)

class ProfileView(APIView):
    permission_classes = (IsAuthenticated,)

    def get(self, request):
        return Response({'username': request.user.username, 'email': request.user.email})

这种方式下,浏览器会自动携带Session Cookie,无需手动处理Token。

内容的提问来源于stack exchange,提问作者Dani barchen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 15:55:15