Django API测试时遭遇CSRF验证失败问题求助
解决Django API测试时的CSRF 403错误
问题场景
首次用Django开发API,通过Postman向http://localhost:8000/arithmetic/发送POST请求,请求JSON内容如下:
{ "expression": "1 + 2 × 3" }
收到403 Forbidden响应,核心错误提示:CSRF token from the 'X-Csrftoken' HTTP header has incorrect length
完整错误响应
<!DOCTYPE html> <html lang="en"> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"> <meta name="robots" content="NONE,NOARCHIVE"> <title>403 Forbidden</title> <style type="text/css"> html * { padding: 0; margin: 0; } body * { padding: 10px 20px; } body * * { padding: 0; } body { font: small sans-serif; background: #eee; color: #000; } body>div { border-bottom: 1px solid #ddd; } h1 { font-weight: normal; margin-bottom: .4em; } h1 span { font-size: 60%; color: #666; font-weight: normal; } #info { background: #f6f6f6; } #info ul { margin: 0.5em 4em; } #info p, #summary p { padding-top: 10px; } #summary { background: #ffc; } #explanation { background: #eee; border-bottom: 0px none; } </style> </head> <body> <div id="summary"> <h1>Forbidden <span>(403)</span></h1> <p>CSRF verification failed. Request aborted.</p> </div> <div id="info"> <h2>Help</h2> <p>Reason given for failure:</p> <pre> CSRF token from the 'X-Csrftoken' HTTP header has incorrect length. </pre> <p>In general, this can occur when there is a genuine Cross Site Request Forgery, or when Django’s CSRF mechanism has not been used correctly. For POST forms, you need to ensure:</p> <ul> <li>Your browser is accepting cookies.</li> <li>The view function passes a <code>request</code> to the template’s <code>render</code> method.</li> <li>In the template, there is a <code>{% csrf_token %}</code> template tag inside each POST form that targets an internal URL.</li> <li>If you are not using <code>CsrfViewMiddleware</code>, then you must use <code>csrf_protect</code> on any views that use the <code>csrf_token</code> template tag, as well as those that accept the POST data.</li> <li>The form has a valid CSRF token. After logging in in another browser tab or hitting the back button after a login, you may need to reload the page with the form, because the token is rotated after a login.</li> </ul> <p>You’re seeing the help section of this page because you have <code>DEBUG = True</code> in your Django settings file. Change that to <code>False</code>, and only the initial error message will be displayed. </p> <p>You can customize this page using the CSRF_FAILURE_VIEW setting.</p> </div> </body> </html>
现有代码
算术应用的views.py
import json from django.shortcuts import render from django.http import HttpResponse, JsonResponse # Create your views here. def parse_request(str): if '×' in str: str = str.replace('×', '*') if '÷' in str: str = str.replace('÷', '/') def calculate(request): if request.method == 'POST': # parse the json object body = json.loads(request.body) expression = body['expression'] return JsonResponse({ 'response': expression }) else: return JsonResponse({ 'error': 'invalid request method' })
算术应用的urls.py
from django.urls import path from . import views urlpatterns = [ path('', views.calculate) ]
主项目的urls.py
from django.contrib import admin from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), path('arithmetic/', include('arithmetic.urls')) ]
解决方案
你开发的是供React前端调用的API,Django默认的CSRF保护主要针对浏览器表单提交场景,API场景下不需要,可通过以下两种方式解决:
方式一:给视图添加csrf_exempt装饰器
直接修改算术应用的views.py,导入并使用csrf_exempt装饰器跳过CSRF验证:
import json from django.shortcuts import render from django.http import HttpResponse, JsonResponse from django.views.decorators.csrf import csrf_exempt # 新增导入 def parse_request(str): if '×' in str: str = str.replace('×', '*') if '÷' in str: str = str.replace('÷', '/') @csrf_exempt # 添加装饰器 def calculate(request): if request.method == 'POST': body = json.loads(request.body) expression = body['expression'] return JsonResponse({'response': expression}) else: return JsonResponse({'error': 'invalid request method'})
方式二:使用Django REST Framework的APIView(推荐)
如果后续要扩展API功能,建议使用更规范的Django REST Framework:
- 先安装依赖:
pip install djangorestframework - 在项目settings.py的
INSTALLED_APPS中添加'rest_framework' - 修改views.py:
from rest_framework.views import APIView from rest_framework.response import Response from django.http import JsonResponse class CalculateView(APIView): def post(self, request): expression = request.data.get('expression') # 可调用parse_request处理表达式 return Response({'response': expression}) def get(self, request): return JsonResponse({'error': 'invalid request method'})
- 修改算术应用的urls.py:
from django.urls import path from . import views urlpatterns = [ path('', views.CalculateView.as_view()) ]
测试说明
修改代码后重启Django服务,再用Postman发送POST请求即可正常访问。后续对接React前端时,直接发送JSON请求即可,无需处理CSRF token。
内容的提问来源于stack exchange,提问作者ben_11
相关产品推荐
相关产品推荐

