Backend - Django CSRF 跨域请求伪造

2024-02-02 07:12

本文主要是介绍Backend - Django CSRF 跨域请求伪造,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

一、CSRF & XSS

(一)CSRF

1. 含义

2. 攻击原理

(1)浏览器特点

(2)攻击方式

(二)XSS

1. 含义

2. 攻击原理

(三)二者区别

二、Django Ajax CSRF 防御

(一)令牌同步模式(Synchronizer Token Pattern,简称STP)

1. 原理

2. 设置验证

(二)双重cookie验证(Double Submit Cookie)

1. 原理

2. 设置验证

(三)X-Csrf-Token验证(Cookie-to-header token)

1. 原理

2. 设置验证

三、设定 CSRF 验证

(一)settings.py

(二)base.html

1. 针对 ajax 请求,body 里添加{% csrf_token %}

2. 针对 form 表单,form 表单里添加{% csrf_token %}

(三)JS

1. 针对 双重cookie验证

(1)方法1

(2)方法2

2. 针对 X-Csrf-Token验证(Cookie-to-header token)

(1)方法1

3. 针对所有模式的综合验证

(1)写入位置

(2)引入顺序

四、关闭 CSRF 防御功能

1. 方法1:全局禁用

2. 方法2:局部禁用

五、Django CSRF 的控制台Error

(一)Reason given for failure: CSRF cookie not set.

1. 原因

2. 解决

(二)CSRF verification failed. Request aborted.

1. 原因

(1)原因1:csrf_token 过期

(2)原因2:请求头的 csrf_token 与session存储的token不匹配

(3)原因3:模板里没有csrfmiddlewaretoken


一、CSRF & XSS

(一)CSRF

1. 含义

        跨站请求伪造(Cross-site Request Forgery )。

2. 攻击原理

(1)浏览器特点

同个浏览器上,无论是目标网站A还是其他网站B,发送对目标网站A的HTTP请求,都会自动带上目标网站A的cookie,发送给服务端。

(2)攻击方式

同个浏览器上,当用户登录了目标网站(已登录状态),再进入攻击网站,攻击网站发送对目标网站的HTTP请求,则会自动带上“已登录的目标网站”的cookie,就可以进行攻击服务端。

(二)XSS

1. 含义

跨站脚本攻击(Cross-Site Scripting,为了和 CSS 区分,则简称 XSS)。

2. 攻击原理

在目标网站上注入恶意脚本进行攻击。(攻击者提交恶意代码,浏览器再执行恶意代码,篡改了网页)

(三)二者区别

CSRF 是 HTTP 问题,XSS 是代码注入问题。

CSRF需登录目标网站,XSS不用登录。

二、Django Ajax CSRF 防御

(一)令牌同步模式(Synchronizer Token Pattern,简称STP)

1. 原理

(1)找到数据库Session的session_csrftoken参数。成功登录网站后,后端随机产生一个csrftoken值,并把该值保存在数据库Session参数中。

(2)找到网页模板的隐藏csrfmiddlewaretoken名的标签。初始化某界面时,前端模板会根据{% csrf_token %}生成一个隐藏的name='csrfmiddlewaretoken'的input标签,存放后端随机生成的csrftoken值。

(3)用户进行 ajax post 请求。post请求时,csrfmiddlewaretoken值会一并放在请求数据(或头信息)中,发送给后端。后端会根据前端csrfmiddlewaretoken的 value值、和服务端数据库 public.django_session 表的 session_csrftoken参数值,判断两个csrf_token解密后的值是否一致。

(4)一致则正常访问,不一致则拒绝访问。

2. 设置验证

在第三点中。

(二)双重cookie验证(Double Submit Cookie)

1. 原理

(1)找到浏览器cookie的csrftoken。成功登录网站后,整个浏览器中Cookie的csrftoken属性,存放后端随机生成的csrftoken值。

(2)找到网页模板的隐藏csrfmiddlewaretoken名的标签。初始化某界面时,前端模板会根据{% csrf_token %}生成一个隐藏的 name='csrfmiddlewaretoken' 的input标签,存放后端随机生成的csrftoken值。

(3)用户进行 ajax post 请求。post请求时,csrfmiddlewaretoken值会一并放在请求数据(或头信息)中,发送给后端。后端会根据前端csrfmiddlewaretoken的 value值、和浏览器Cookie的csrftoken值,判断两个csrf_token解密后的值是否一致。

(4)一致则正常访问,不一致则拒绝访问。

2. 设置验证

在第三点中。

(三)X-Csrf-Token验证(Cookie-to-header token)

1. 原理

(1)确保同源政策。

(2)系统主要使用JavaScript进行交互。(因为恶意攻击无法读取cookie值并复制到HTTP请求头中)

(3)将cookie上的token复制到HTTP请求头中。

(4)后端验证HTTP请求头中token的存在和完整性。

(5)X-Csrf-Token头存在且完整,则正常访问,否则拒绝访问。

2. 设置验证

在第三点中。

三、设定 CSRF 验证

以下主要针对基于 django 使用 ajax 发送 post 请求时的验证。

(一)settings.py

        MIDDLEWARE里添加'django.middleware.csrf.CsrfViewMiddleware'  # 设置CSRF检测功能

(二)base.html

1. 针对 ajax 请求,body 里添加{% csrf_token %}

例如:

<body id="body">{% csrf_token %}<div>{% block content %} {% endblock %}</div>
</body>

渲染后:

<body id="body"><input type="hidden" name="csrfmiddlewaretoken" value="vUAPUcghecxAGlraGaFGbikXz3SOPcWtmMtk8o1UQ1PpYYAhxg2cAiAaLyQ9HEY9" /><div>插入的子模板</div>
</body>

2. 针对 form 表单,form 表单里添加{% csrf_token %}

因为若在 base.html 中加入 {% csrf_token %},是不在 form 表单的范围内。所以需要在 form 表单里添加。

例如:

<form action="http://127.0.0.1:8080/myApp/test" method=POST>{% csrf_token %}<input type="submit"/>
</form>

(三)JS

1. 针对 双重cookie验证

(1)方法1

        后端将csrftoken传到前端(放置在隐藏标签里),发送post请求时,请求数据data中加上csrftoken,一起发送给后端。

        在base.html中的script里写上。

$.ajaxSetup({data: {csrfmiddlewaretoken: '{{ csrf_token }}' },
});
(2)方法2

        后端将csrftoken传到前端(放置在隐藏标签里),发送post请求时,请求数据data中加上csrftoken。

        在base.html中的script里写上。

$.ajaxSetup({data: {csrfmiddlewaretoken: $('[name="csrfmiddlewaretoken"]').val()},
});

2. 针对 X-Csrf-Token验证(Cookie-to-header token)

(1)方法1

        cookie中存在csrftoken,请求头headers中加上csrftoken。

        在base.html中的script里写上。

        前提:

                ① 引入jquery-3.1.1.min.js和jquery.cookie.js

                ② 引入顺序:jQuery库文件必须先于cookie文件。

$.ajaxSetup({headers:{ "X-CSRFtoken":$.cookie("csrftoken")},
});

3. 针对所有模式的综合验证

(1)写入位置

        前面两个验证的所有方法只能写在html中,不能写到外部js文件。因为{{ csrf_token }} 渲染在模板上,若以外部文件引入,则不能执行。

        以下代码可以写在外部js文件里,并在 base.html 里引入该js文件。

(2)引入顺序

        该 js 文件的引入顺序必须在 jquery.js 文件之后。

/*** 【 Cross Site Request Forgery TOKEN 】*  Forbidden 403 - CSRF check with an AJAX POST request in Django.*/
jQuery(document).ajaxSend(function (event, xhr, settings) {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;}function sameOrigin(url) {// url could be relative or scheme relative or absolutelet host = document.location.host; // host + portlet protocol = document.location.protocol;let sr_origin = '//' + host;let origin = protocol + sr_origin;// Allow absolute or scheme relative URLs to same originreturn (url === origin || url.slice(0, origin.length + 1) === origin + '/') ||(url === sr_origin || url.slice(0, sr_origin.length + 1) === sr_origin + '/') ||// or any other URL that isn't scheme relative or absolute i.e relative.!(/^(\/\/|http:|https:).*/.test(url));}function safeMethod(method) {return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));}if (!safeMethod(settings.type) && sameOrigin(settings.url)) {xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));}
});

四、关闭 CSRF 防御功能

不推荐关闭 CSRF 防御功能,因为取消了 CSRF 防御保护。

1. 方法1:全局禁用

        settings.py中,注释掉'django.middleware.csrf.CsrfViewMiddleware'

2. 方法2:局部禁用

        views.py中,导入from django.views.decorators.csrf import csrf_exempt;

        并给要处理post数据的函数补充@csrf_exempt(post函数有request参数)。

五、Django CSRF 的控制台 Error

(一)Reason given for failure: CSRF cookie not set.

1. 原因

        django 中使用 jquery ajax post 数据出现 403 错误。

        即,settings设置了Django CSRF检测功能(防止跨站请求伪造),需要在django发送post请求时进行字符串验证,但还没有设置CSRF cookie。

2. 解决

(1)第一种:关闭 CSRF 检测功能

(2)第二种:设定 CSRF 验证

(这两种方式在前面第三点中已介绍)

(二)CSRF verification failed. Request aborted.

1. 原因

(1)原因1:csrf_token 过期

        解决:重新登录(若还未写前端登录,则admin登录)

(2)原因2:请求头的 csrf_token 与session存储的token不匹配

        解决:清除浏览器缓存; 重新登录

(3)原因3:模板里没有csrfmiddlewaretoken

        解决:模板中(或表单内)添加 {% csrf_token %} 

这篇关于Backend - Django CSRF 跨域请求伪造的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/669875

相关文章

C#使用HttpClient进行Post请求出现超时问题的解决及优化

《C#使用HttpClient进行Post请求出现超时问题的解决及优化》最近我的控制台程序发现有时候总是出现请求超时等问题,通常好几分钟最多只有3-4个请求,在使用apipost发现并发10个5分钟也... 目录优化结论单例HttpClient连接池耗尽和并发并发异步最终优化后优化结论我直接上优化结论吧,

Java后端接口中提取请求头中的Cookie和Token的方法

《Java后端接口中提取请求头中的Cookie和Token的方法》在现代Web开发中,HTTP请求头(Header)是客户端与服务器之间传递信息的重要方式之一,本文将详细介绍如何在Java后端(以Sp... 目录引言1. 背景1.1 什么是 HTTP 请求头?1.2 为什么需要提取请求头?2. 使用 Spr

如何使用celery进行异步处理和定时任务(django)

《如何使用celery进行异步处理和定时任务(django)》文章介绍了Celery的基本概念、安装方法、如何使用Celery进行异步任务处理以及如何设置定时任务,通过Celery,可以在Web应用中... 目录一、celery的作用二、安装celery三、使用celery 异步执行任务四、使用celery

Django中使用SMTP实现邮件发送功能

《Django中使用SMTP实现邮件发送功能》在Django中使用SMTP发送邮件是一个常见的需求,通常用于发送用户注册确认邮件、密码重置邮件等,下面我们来看看如何在Django中配置S... 目录1. 配置 Django 项目以使用 SMTP2. 创建 Django 应用3. 添加应用到项目设置4. 创建

SpringBoot中Get请求和POST请求接收参数示例详解

《SpringBoot中Get请求和POST请求接收参数示例详解》文章详细介绍了SpringBoot中Get请求和POST请求的参数接收方式,包括方法形参接收参数、实体类接收参数、HttpServle... 目录1、Get请求1.1 方法形参接收参数 这种方式一般适用参数比较少的情况,并且前后端参数名称必须

如何用Docker运行Django项目

本章教程,介绍如何用Docker创建一个Django,并运行能够访问。 一、拉取镜像 这里我们使用python3.11版本的docker镜像 docker pull python:3.11 二、运行容器 这里我们将容器内部的8080端口,映射到宿主机的80端口上。 docker run -itd --name python311 -p

【VUE】跨域问题的概念,以及解决方法。

目录 1.跨域概念 2.解决方法 2.1 配置网络请求代理 2.2 使用@CrossOrigin 注解 2.3 通过配置文件实现跨域 2.4 添加 CorsWebFilter 来解决跨域问题 1.跨域概念 跨域问题是由于浏览器实施了同源策略,该策略要求请求的域名、协议和端口必须与提供资源的服务相同。如果不相同,则需要服务器显式地允许这种跨域请求。一般在springbo

利用Django框架快速构建Web应用:从零到上线

随着互联网的发展,Web应用的需求日益增长,而Django作为一个高级的Python Web框架,以其强大的功能和灵活的架构,成为了众多开发者的选择。本文将指导你如何从零开始使用Django框架构建一个简单的Web应用,并将其部署到线上,让世界看到你的作品。 Django简介 Django是由Adrian Holovaty和Simon Willison于2005年开发的一个开源框架,旨在简

proxy代理解决vue中跨域问题

vue.config.js module.exports = {...// webpack-dev-server 相关配置devServer: {host: '0.0.0.0',port: port,open: true,proxy: {'/api': {target: `https://vfadmin.insistence.tech/prod-api`,changeOrigin: true,p

Java http请求示例

使用HttpURLConnection public static String httpGet(String host) {HttpURLConnection connection = null;try {URL url = new URL(host);connection = (HttpURLConnection) url.openConnection();connection.setReq