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

使用Fetch API向Django后端传递认证Session ID时的用户认证问题

问题解决:Django Fetch请求中request.user为匿名用户及用户认证风险处理

一、报错直接原因

你的错误出在视图逻辑里:虽然判断了request.user.is_anonymous但只写了pass,后续代码依然用request.user执行Card.objects.get_or_create(user=user)——而匿名用户(AnonymousUser)没有合法的数据库ID值,ORM尝试把匿名用户对象传入需要数字ID的字段时,自然抛出类型错误。

二、为什么Session认证没生效?

排查以下几个关键节点:

  • 用户是否真的登录?:先在浏览器访问Django后台或其他需登录的页面,确认当前会话处于已登录状态,否则request.user必然是匿名用户。
  • 跨域/同源问题?:如果前端页面和Django后端域名/端口不一致(比如前端在localhost:3000,后端在8000),需要配置跨域支持:
    • 安装django-cors-headers,在INSTALLED_APPS中添加corsheaders,中间件列表中加入corsheaders.middleware.CorsMiddleware
    • 设置CORS_ALLOW_CREDENTIALS = True,CORS_ALLOWED_ORIGINS包含前端域名(如["http://localhost:3000"])
  • Fetch的credentials配置:你已经写了credentials: 'include',这个是正确的,确保请求会携带Session Cookie。

三、正确处理逻辑(拦截匿名用户+避免冒充风险)

1. 视图层强制拦截未登录用户

直接用Django自带的login_required装饰器,阻止未登录用户访问该接口:

from django.contrib.auth.decorators import login_required

@login_required
def add_to_card(request, slug):
    auction = get_object_or_404(Auction, slug=slug)
    user = request.user
    
    data = {'added': False}
    
    card, created = Card.objects.get_or_create(user=user)
    card_item, created = CardItem.objects.get_or_create(card=card, auction=auction)
    
    if created:
        data['added'] = True
    else:
        card_item.delete()
    
    return JsonResponse(data)

未登录用户访问会返回302跳转,前端可捕获状态码引导用户登录。

2. 绝对禁止前端传递用户ID

你担心的用户冒充风险完全正确——前端传的任何用户标识都不可信,必须依赖Django后端通过Session Cookie验证的request.user。Session Cookie由后端生成,前端只能被动携带,无法篡改(除非Session泄露,可通过HTTPS、Session过期策略缓解)。

3. 自定义未登录提示(可选)

如果需要对未登录用户返回JSON提示而非跳转:

def add_to_card(request, slug):
    if request.user.is_anonymous:
        return JsonResponse({'error': '请先登录'}, status=401)
        
    auction = get_object_or_404(Auction, slug=slug)
    user = request.user
    
    data = {'added': False}
    
    card, created = Card.objects.get_or_create(user=user)
    card_item, created = CardItem.objects.get_or_create(card=card, auction=auction)
    
    if created:
        data['added'] = True
    else:
        card_item.delete()
    
    return JsonResponse(data)

前端捕获401状态码后,弹出登录提示或跳转登录页。

四、额外检查点

  • 本地开发时,确认Django的SESSION_COOKIE_SECURE设为False;生产环境用HTTPS时需设为True。
  • 打开浏览器控制台的网络面板,查看请求头是否携带了sessionid和csrftoken两个Cookie。

内容的提问来源于stack exchange,提问作者Minecraft PC

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 04:35:59