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

Django无需@csrf_exempt解决CSRF cookie未设置的禁止访问问题

安全解决方案(无需@csrf_exempt)

方案1:浏览器端页面调用(适配Django原生CSRF机制)

如果是通过Django渲染的前端页面发起请求,需遵循Django的CSRF验证流程:

  • 在模板中引入CSRF Token:通过{% csrf_token %}生成隐藏表单字段,或通过JS读取浏览器Cookie中的csrftoken值
  • 发起请求时,将Token放入请求头X-CSRFToken中

示例JS代码:

// 获取Cookie中的CSRF Token
function getCookie(name) {
    let cookieValue = null;
    if (document.cookie && document.cookie !== '') {
        const cookies = document.cookie.split(';');
        for (let i = 0; i < cookies.length; i++) {
            const cookie = cookies[i].trim();
            if (cookie.substring(0, name.length + 1) === (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
}

// 发起POST请求
const csrftoken = getCookie('csrftoken');
fetch('/api/calculator/score/', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        'X-CSRFToken': csrftoken,
    },
    body: JSON.stringify(yourRequestData),
})
.then(response => response.json())
.then(data => console.log(data));

注意:确保前端页面由Django视图渲染,否则浏览器无法获取CSRF Cookie。

方案2:非浏览器客户端调用(Token认证)

如果是外部脚本、服务调用接口,推荐使用Token替代CSRF验证,以Django REST Framework的TokenAuthentication为例:

  1. 安装并配置DRF:
    • 安装依赖:pip install djangorestframework
    • 在settings.py的INSTALLED_APPS中添加:
      INSTALLED_APPS = [
          # 其他应用
          'rest_framework',
          'rest_framework.authtoken',
      ]
      
    • 执行迁移:python manage.py migrate
  2. 为调用方用户生成Token:
    • 通过Django后台创建用户,或执行命令:python manage.py drf_create_token <用户名>
  3. 修改视图添加认证:
    from rest_framework.decorators import api_view, authentication_classes, permission_classes
    from rest_framework.authentication import TokenAuthentication
    from rest_framework.permissions import IsAuthenticated
    import requests
    from django.http import JsonResponse
    
    @api_view(['POST'])
    @authentication_classes([TokenAuthentication])
    @permission_classes([IsAuthenticated])
    def post_for_score(request): 
        # DRF自动解析JSON请求体,无需手动解码
        body_dict = request.data
        
        flask_url = '<<my flask/amazon url here>>'
        res = requests.post(flask_url, json=body_dict)
        if res.status_code == 200:
            return JsonResponse(res.json()) 
        else:
            return JsonResponse({"error": str(res.content)})
    
  4. 调用接口时携带Token:
    curl -X POST http://127.0.0.1:8000/api/calculator/score/ \
        -H "Content-Type: application/json" \
        -H "Authorization: Token 你的Token值" \
        -d '{"key": "value"}'
    

方案3:受限来源的CSRF豁免(仅信任特定调用方)

如果仅需对指定信任来源放开CSRF,可在视图中添加来源校验后再豁免:

from django.views.decorators.csrf import csrf_exempt
from django.http import JsonResponse
import json
import requests

def post_for_score(request):
    # 校验请求来源是否在信任列表
    allowed_origins = [
        '<<my flask/amazon url here>>',
        "http://127.0.0.1:8000", 
        "http://localhost:8000"
    ]
    origin = request.META.get('HTTP_ORIGIN')
    if origin not in allowed_origins:
        return JsonResponse({"error": "Invalid origin"}, status=403)
    
    body_unicode = request.body.decode('utf-8')
    body_dict = json.loads(body_unicode)

    flask_url = '<<my flask/amazon url here>>'
    res = requests.post(flask_url, json=body_dict)
    if res.status_code == 200:
        return JsonResponse(res.json()) 
    else:
        return JsonResponse({"error": str(res.content)})

# 仅对通过来源校验的请求豁免CSRF
post_for_score = csrf_exempt(post_for_score)

注:该方案安全性弱于Token认证,仅适用于完全信任的调用方。

补充:为什么CSRF_TRUSTED_ORIGINS未生效?

CSRF_TRUSTED_ORIGINS的作用是允许跨域请求携带CSRF Cookie,而非直接豁免CSRF验证。即使配置了该参数,请求方仍需携带CSRF Token或Cookie,否则依然会触发Forbidden错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 08:42:26