Django项目学习之CSRF cookie not set.报错

什么是 CSRF

CSRF, Cross Site Request Forgery, 跨站点伪造请求。举例来讲,某个恶意的网站上有一个指向你的网站的链接,如果某个用户已经登录到你的网站上了,那么当这个用户点击这个恶意网站上的那个链接时,就会向你的网站发来一个请求,你的网站会以为这个请求是用户自己发来的,其实呢,这个请求是那个恶意网站伪造的。

csrf原理
csrf要求发送post,put或delete请求的时候,是先以get方式发送请求,服务端响应时会分配一个随机字符串给客户端,客户端第二次发送post,put或delete请求时携带上次分配的随机字符串到服务端进行校验


当我们写好某个路由,需要利用post请求发送ajax到后台的时候,会发现,报出如下警告。
在这里插入图片描述
然后浏览器会有如下错误:
在这里插入图片描述
这是因为在post请求时,我们没有加CsrfToken字段,而在Django项目中,这字段相当于提交数据的令牌,是必须的。如果在开发阶段可以直接把它注释掉,这样就不会报错。
在这里插入图片描述
如果项目完成之后,需要开启这个中间件,又该如何解决报错的问题呢。

此时又到了我们紧张刺激的看源码时候了。
先看下图:在这里插入图片描述
该字段是不是和上面的WARNINGN提示的错误文本很相似呢。

而我们的浏览器飘红报错又是出自哪里呢?
在这里插入图片描述
该框中的:REASON_NO_CSRF_COOKIE貌似在告诉我们,报错的原因是你的请求里没有带上CSRF cookie;

我们可以怎样获取cookie值呢?
有个很简单的办法,在浏览器中按下F12,进入开发模式。
然后输入命令:javascript:alert(document.cookie);浏览器便会把当前网页的cookie值以弹窗的方式发出来。

但是在没有注释掉csrf中间件的时候,我们利用这个命令,会发现它弹出的窗口有个cookie值

在这里插入图片描述
该cookie值的key是csrftoken.这时如果cookie中携带的有其他内容(以分号分隔),就要对cookie进行处理,比如说百度翻译的cookie值:
在这里插入图片描述

这时,在js里面写个getCookie方法,用于整理cookie,以获取csrf验证用的csrfToken:

    function getCookie(name) {
        let cookieValue = null;
        if (document.cookie && document.cookie !== '') {
            let cookies = document.cookie.split(';');
            for (let i = 0; i < cookies.length; i++) {
                let cookie = jQuery.trim(cookies[i]);
                // 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;
    }

然后获取所需字段就行了。
另外还需知道发送到后端的Ajax请求还需携带的csrf令牌的字段名,而这在cookie中是看不到的。
这时先看看源码吧。
在这里插入图片描述
这是对应的csrf中间件。

当用ajax发送请求时,请求头需要携带上的字段名是:‘X-CSRFToken’,而它的值对应的是cookie里面csrftoken的值。
在这里插入图片描述

所以我们需要在Ajax请求头加上。
在这里插入图片描述
然后在需要POST请求的表单元素里面加上:
{% csrf_token %}

但是这种写法需要在每个表单都加上{% csrf_token %}

还有一种方法,不需要为每个表单加上{% csrf_token %},那就是自定义一个中间件。(中间件是介于request 和 response 处理之间的一道处理过程,用于全局范围改变Django的输入和输出,简单的来说中间件是帮助我们在视图函数指向之前和执行之后都可以做一些额外的操作)

首先找到原本用于csrf认证的类:
浏览器发送post请求,该类可用于处理请求,找到该函数如下:
在这里插入图片描述

注意它上面还有个get_token函数:
在这里插入图片描述
在这里插入图片描述
在自定义的子类中,重写的处理请求函数,利用get_token函数返回post表单的CSRF令牌,交给process_request进行处理。
然后再注册中间件就可以了

from django.middleware.csrf import get_token
from django.utils.deprecation import MiddlewareMixin

# 继承MiddlewareMixin类
class Middleware(MiddlewareMixin):
	# 重写函数处理请求

	def process_request(self, request):
		# 调用包里的get_token函数,拿到令牌
		get_token(request)

随后再设置文件中注册中间件即可。


补充

在正确配置以上信息的情况下
还会引起csrf报错的其他原因:
在利用Post请求提交表单的时候,如果利用submit方法的话,需选取的是整个表单元素,如果想选取某个按钮利用click方法进行Post请求提交表单的话,只需选取按钮元素就行。如果submit方法选取的不是整个表单元素,而是选了提交按钮的话,也会报csrf丢失或不正确的错误。
在这里插入图片描述
在这里插入图片描述

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这个错误是由于DjangoCSRF保护机制引起的,它需要确保每个POST请求都具有与会话关联的CSRF令牌。 在Django中,每个POST请求都需要在请求中包含一个名为`csrfmiddlewaretoken`的CSRF令牌。如果请求中不包含这个令牌,Django会抛出`Forbidden (CSRF cookie not set.)`错误。 为了解决这个问题,您需要在POST请求的表单中包含CSRF令牌。例如,在您的HTML表单中,可以添加以下代码: ```html {% csrf_token %} ``` 这将在表单中添加一个隐藏字段,其中包含与当前会话关联的CSRF令牌。当用户提交表单时,这个令牌将与请求一起发送,以通过CSRF保护。 如果您使用的是AJAX请求,可以将CSRF令牌作为请求头发送。例如,在JavaScript中,可以添加以下代码: ```javascript function getCookie(name) { var cookieValue = null; if (document.cookie && document.cookie !== '') { var cookies = document.cookie.split(';'); for (var i = 0; i < cookies.length; i++) { var cookie = cookies[i].trim(); if (cookie.substring(0, name.length + 1) === (name + '=')) { cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); break; } } } return cookieValue; } var csrfToken = getCookie('csrftoken'); $.ajax({ ... headers: { 'X-CSRFToken': csrfToken }, ... }); ``` 这将在请求头中添加一个名为`X-CSRFToken`的头,其中包含与当前会话关联的CSRF令牌。这样,您的AJAX请求将通过CSRF保护。 请注意,如果您使用的是第三方库或框架,例如Django REST framework或jQuery,它们可能会自动处理CSRF令牌。在这种情况下,您不需要手动添加CSRF令牌。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值