问题:Post请求CSRF认证失败
问题:使用ajax向后台发送post请求,提示CSRF验证失败,报403,原因是因为django中自带了防止CSRF攻击的功能,GET请求不需要CSRF认证,POST请求需要正确认证才能得到正确的放回结果。
Django CSRF认证中间件
Django默认是开启这个中间件的,每个POST请求是都会通过这个中间件认证。
1. 表单处理
如果是表单,在POST表单中直接加入{ % csrf_token% },这在POST请求时,就不会报CSRF认证错误。在表单的任何位置加入都可以
<form method="POST" action="/post-url/">{% csrf_token %} // 加上这一句就不会提示CSRF认证错误</form>
2. Ajax Post请求
官网原话:
当 CSRF_USE_SESSIONS 和 CSRF_COOKIE_HTTPONLY 为 False 时获取令牌,默认为False的,才能使用下面这种解决方式。
解决方式:
在每个POST请求中把CSRF作为POST数据传递进来。在每个http请求头中,自定义的X-CSRFToken头,这个是默认名称(不要写错了)。
2.1 CSRF作为POST数据传递
在Js文件中直接复制官网提供的获取CSRF认证的代码。然后在Ajax请求中data属性中添加CSRF。
示例:
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();// Does this cookie string begin with the name we want?if (cookie.substring(0, name.length + 1) === (name + '=')) {cookieValue = decodeURIComponent(cookie.substring(name.length + 1));break;}}}return cookieValue;}const csrftoken = getCookie('csrftoken');// Ajax请求$.ajax({url:'update/',type:'POST',data:{"post_data":post_data,"csrf_token":csrftoken, // 将csrftoken传给Django}})
这种方式是在网上找的,但是不知道什么问题,我在django==3.2.11居然没有生效,所以换了另一种解决方式。
2.2 添加请求头
在每个http请求头中,添加自定义属性X-CSRFToken
,并把csrftoken赋值给它。
示例:
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();// Does this cookie string begin with the name we want?if (cookie.substring(0, name.length + 1) === (name + '=')) {cookieValue = decodeURIComponent(cookie.substring(name.length + 1));break;}}}return cookieValue;}const csrftoken = getCookie('csrftoken');$.ajax({url:'update/',type:'POST',data:{"post_data":post_data,},beforeSend: function(request) {request.setRequestHeader("X-CSRFToken", csrftoken);// X-CSRFToken 不要写错了,默认是这个名称}})