Django API Post 403 FORBIDDEN

本文介绍了在使用Django框架时遇到的CSRF验证失败问题及其原因,并提供了两种解决方案:一种是在表单中加入CSRF令牌;另一种是对于API接口使用`csrf_exempt`装饰器来禁用CSRF检查。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 测试Django编写的POST方法的API,报出下面的错误:

``` Forbidden (403) CSRF verification failed. Request aborted. You are seeing this message because this site requires a CSRF cookie when submitting forms. This cookie is required for security reasons, to ensure that your browser is not being hijacked by third parties. If you have configured your browser to disable cookies, please re-enable them, at least for this site, or for 'same-origin' requests. ```

2. ROOT CAUSE

Django提供了CSRF的防护。CSRF是跨站点请求伪造,简单来说就是用户在访问受信任网站后,浏览器记录了受信任网站的cookie,此时用户在不登出受信任网站的同时访问了危险网站,危险网站的请求和cookie一起到达服务器,服务器Session未过期的时候,就误认为该请求是用户发出的,从而被危险网站利用。在建立Django项目的时候,setting.py中就会有 ``` MIDDLEWARE = [ .... 'django.middleware.csrf.CsrfViewMiddleware', .... ] ```

3. solution

1. 如果是表单,可以在模版文件中加入` {% csrf_token %} `,而且模版的函数使用`reander`。 2. 如果是API也就没有模版,此时无法添加` {% csrf_token %} `,最后找到方法可以使用 `django.views.decorators.csrf` 的 `csrf_exempt`函数对POST的API函数进行修饰。可以使其避免CSRF安全检查机制。 例:
from django.views.decorators.csrf import csrf_exempt
@csrf_exempt
def add_event(request):

看网上又说将'django.middleware.csrf.CsrfViewMiddleware'注释掉,最好还是不要如此做,保持django默认安全机制,保持其安全特性。

### Django403 Forbidden 错误的原因 Django 的 `403 Forbidden` 错误通常是由 CSRF 验证失败引起的。当客户端发送的请求缺少有效的 CSRF Token 或者该令牌不匹配时,服务器会返回此错误[^3]。 #### 原因分析 1. **CSRF Token 缺失**: 如果前端页面未包含 `{% csrf_token %}` 标签,则 POST 请求无法通过 CSRF 验证。 2. **CSRF Middleware 被禁用**: 若在设置文件中移除了 `'django.middleware.csrf.CsrfViewMiddleware'`,则可能导致某些安全机制失效[^4]。 3. **Ajax 请求未携带 Token**: 对于 AJAX 请求而言,如果未正确传递 CSRF Token 到后端服务端也会拒绝处理并抛出 403 错误[^2]。 --- ### 解决方案 以下是几种常见的解决方式: #### 方法一:确保表单中有 `{% csrf_token %}` 对于 HTML 表单提交的情况,在 `<form>` 标签内部加入 `{% csrf_token %}` 是必要的。例如: ```html <h1>用户登录</h1> <form method="post" action="/login/"> {% csrf_token %} <input type="text" name="user" placeholder="用户名"> <input type="password" name="pwd" placeholder="密码"> <input type="submit" value="提交"> </form> ``` 这样可以保证每次 HTTP POST 请求都附带合法的 CSRF Token[^5]。 #### 方法二:调整中间件配置 如果你确实不需要启用全局范围内的 CSRF 功能(比如开发 API 接口),可以选择临时关闭它。具体操作是在项目的 settings 文件里注释掉对应的 middleware 条目: ```python MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', # 'django.middleware.csrf.CsrfViewMiddleware', # 关闭 CSRF 检查 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ] ``` 注意这种方法可能降低应用的安全级别,因此仅适用于特定场景下的调试阶段。 #### 方法三:针对 Ajax 请求特别处理 为了使 JavaScript 发起的异步调用能够顺利通过验证,需手动获取当前网页上的隐藏字段 `_csrfmiddlewaretoken` 并将其作为自定义头部参数 X-CSRFToken 添加到 XMLHttpRequest 实例上。下面是一个基于 jQuery 库的例子演示如何实现这一点: ```javascript $.ajaxSetup({ beforeSend: function(xhr, settings){ if (!/^(GET|HEAD|OPTIONS|TRACE)$/i.test(settings.type)) { xhr.setRequestHeader('X-CSRFToken', $('meta[name=csrf-token]').attr('content')); } } }); // 同时记得在 base.html 加入 meta tag 存储 token <meta name="csrf-token" content="{{ csrf_token }}"> ``` 另外一种更简洁的方式则是利用 fetch api 设置 headers 字段完成同样目的: ```javascript fetch('/url/',{ method:'POST', credentials:"same-origin", headers:{ "Content-Type":"application/json;charset=UTF-8", "X-CSRFToken":document.querySelector('[name=csrfmiddlewaretoken]').value, }, body:JSON.stringify(data), }) .then(response=>response.json()) .catch(error=>console.error('Error:',error)); ``` 以上两种做法都可以有效规避因为忘记附加必要信息而导致被拦截的现象发生. --- ### 总结 综上所述,要彻底根除此类现象的发生可以从以下几个方面入手考虑改进措施——确认模板渲染过程中已嵌套进去了相应的占位符;合理规划项目架构避免不必要的复杂度引入额外风险因素;最后再配合恰当的技术手段妥善处置特殊情况即可达成目标效果. ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值