csrf 跨站请求伪造

一、简介

django为用户实现防止跨站请求伪造的功能,通过中间件 django.middleware.csrf.CsrfViewMiddleware 来完成。

1.1 第1次来访问的时候(get方法),先拿到字符串;下次再来访问的时候(post方法)也必须带着这一串字符串才能成功。CSRF是指提交数据的时候必须通过验证。cookie和session是关于用户名/密码保存的。

第2种方法

form表单提交的时候,加上它就可以了。

这个CSRF字符串不仅在表单里面有了,在cookie里面也有了。

当用form表单提交的时候,把随机字符串和cookie值都发过去了。

1.2 如果用Ajax往后台发数据的时候,只需要把cookie值拿到,放到请求头里面发过去就可以了。

先来看一个没有加cookie值的Ajax请求过程:

login.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/login/" method="POST" >
{%csrf_token%}
<input type="text" name="user" placeholder="user"/>
<input type="text" name="pwd" placeholder="pwd"/>
<input type="checkbox" name="remember" value="1"/> 10秒免登录
<input type="submit" value="提交"/>
<input id="btn" type="button" value="按钮"/>
</form>
<script src="/static/jquery-1.12.4.js"></script>
<script src="/static/jquery.cookie.js"></script>
<script>
$(function(){
$('#btn').click(function(){
$.ajax({
url:'/login/',
type:"POST",
data:{'user':'root','pwd':'123'},
success:function(arg){ } }) }) })
</script>
</body>
</html>

此时如果登录的话,则通不过CSRF验证,报403错误。做这个实例的时候,不要在setting里面注释这句

'django.middleware.csrf.CsrfViewMiddleware'

带上随机字符串的话, 才能登录成功。从cookie里面先把随机字符串获取到。获取方法如下:$.cookie('csrftoken')

 但是后台需要通过key去获取这个值,那么这个值对应的key是什么呢?通过打印settings.CSRF_HEADER_NAME可知,

key是HTTP_X_CSRFTOKEN, HTTP_ 是django自动给加上的,所以我们发送的时候,只需要把key设置成 X_CSRFTOKEN就可以了。 

由于请求头里面不能出现下划线,所以最终设置的时候应该写成 X-CSRFTOKEN。

(1) 下面的图说明key是啥样的

(2)下面这个例子来验证HTTP_是Django自动添加的。

(3)理论上我们把请求头设置成X_CSRFTOKEN 就可以了。 但是由于Django有要求,请求头里面不能出现下划线,所以最终我们把请求头设置成X-CSRFTOKEN 的样子。按照官网推荐,建议写成

X-CSRFtoken。

headers:{'X-CSRFtoken':$.cookie('csrftoken')},

login.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/login/" method="POST" >
{%csrf_token%}
<input type="text" name="user" placeholder="user"/>
<input type="text" name="pwd" placeholder="pwd"/>
<input type="checkbox" name="remember" value="1"/> 10秒免登录
<input type="submit" value="提交"/>
<input id="btn" type="button" value="按钮"/>
</form>
<script src="/static/jquery-1.12.4.js"></script>
<script src="/static/jquery.cookie.js"></script>
<script>
$(function(){
$('#btn').click(function(){
$.ajax({
url:'/login/',
type:"POST",
data:{'user':'root','pwd':'123'},
headers:{'X-CSRFtoken':$.cookie('csrftoken')},
success:function(arg){ } }) }) })
</script>
</body>
</html>

此时可以用Ajax提交可以成功

1.3  Form表单提交与Ajax方法提交的不同之处在于,去不同的地方拿csrf_token

在 Ajax中写headers太麻烦了,可以用setup 对整个页面中所有的Ajax操作做一个配置。

表示在发送ajax之前,会先执行一下那个函数。

xhr是XMLHttpRequest 对象,所有的ajax操作底层用的都是它。

login.html--------示例中有2个Ajax

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/login/" method="POST" >
{%csrf_token%}
<input type="text" name="user" placeholder="user"/>
<input type="text" name="pwd" placeholder="pwd"/>
<input type="checkbox" name="remember" value="1"/> 10秒免登录
<input type="submit" value="提交"/>
<input id="btn1" type="button" value="按钮1"/>
<input id="btn2" type="button" value="按钮2"/>
</form>
<script src="/static/jquery-1.12.4.js"></script>
<script src="/static/jquery.cookie.js"></script>
<script>
$(function(){
$.ajaxSetup({
beforeSend:function(xhr,settings){
xhr.setRequestHeader('X-CSRFtoken',$.cookie('csrftoken'));
}
});
$('#btn1').click(function(){
$.ajax({
url:'/login/',
type:"POST",
data:{'user':'root','pwd':'123'},
//headers:{'X-CSRFtoken':$.cookie('csrftoken')},
success:function(arg){ }
})
});
$('#btn2').click(function(){
$.ajax({
url:'/login/',
type:"POST",
data:{'user':'root','pwd':'123'},
//headers:{'X-CSRFtoken':$.cookie('csrftoken')},
success:function(arg){ }
})
})
})
</script>
</body>
</html>

运行效果:两个Ajax都可以成功提交

程序摘录

login.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/login/" method="POST" >
{%csrf_token%}
<input type="text" name="user" placeholder="user"/>
<input type="text" name="pwd" placeholder="pwd"/>
<input type="checkbox" name="remember" value="1"/> 10秒免登录
<input type="submit" value="提交"/>
<input id="btn1" type="button" value="按钮1"/>
<input id="btn2" type="button" value="按钮2"/>
</form>
<script src="/static/jquery-1.12.4.js"></script>
<script src="/static/jquery.cookie.js"></script>
<script>
$(function(){
$.ajaxSetup({
beforeSend:function(xhr,settings){
xhr.setRequestHeader('X-CSRFtoken',$.cookie('csrftoken'));
}
});
$('#btn1').click(function(){
$.ajax({
url:'/login/',
type:"POST",
data:{'user':'root','pwd':'123'},
//headers:{'X-CSRFtoken':$.cookie('csrftoken')},
success:function(arg){ }
})
});
$('#btn2').click(function(){
$.ajax({
url:'/login/',
type:"POST",
data:{'user':'root','pwd':'123'},
//headers:{'X-CSRFtoken':$.cookie('csrftoken')},
success:function(arg){ }
})
})
})
</script>
</body>
</html>

index.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>欢迎登录:{{username}},{{request.session.username}}</h1>
<a href="/logout/">注销</a>
</body>
</html>

views.py

from django.shortcuts import render,HttpResponse,redirect
# Create your views here.
def login(request):
if request.method=='GET':
return render(request,'login.html')
elif request.method=='POST':
user=request.POST.get('user')
pwd=request.POST.get('pwd')
if user=='root' and pwd=='123':
#生成随机字符串,写到浏览器cookie中,保存在session中。在随机字符串对应的字典中设置相关内容...
# 在session里面设置值
request.session['username']=user
request.session['is_login']=True
if request.POST.get('remember',None)=='1':
#设置超时时间
request.session.set_expiry(10)
return redirect('/index/')
else:
return render(request,'login.html')
def index(request):
#获取当前用户的随机字符串
#根据随机字符串获取对应的信息
#去session中获取值,如果登录成功,显示用户名
if request.session.get('is_login',None):
#return HttpResponse(request.session['username'])
return render(request,'index.html',{'username':request.session['username']})
else:
return HttpResponse('滚')
def logout(request):
request.session.clear()
return redirect('/login/')

urls.py

from django.conf.urls import url
from django.contrib import admin
from app01 import views urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^login/$', views.login),
url(r'^index/$', views.index),
url(r'^logout/$', views.logout),
]

二,而对于django中设置防跨站请求伪造功能有分为全局和局部。

全局:

  中间件 django.middleware.csrf.CsrfViewMiddleware

局部:

注:from django.views.decorators.csrf import csrf_exempt,csrf_protect

  • @csrf_protect,为当前函数强制设置防跨站请求伪造功能,即便settings中没有设置全局中间件。
  • @csrf_exempt,取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件。

csrf_exempt

csrf_protect

settings会得到Ajax中的所有数据

Day22-CSRF跨站请求伪造的更多相关文章

  1. python CSRF跨站请求伪造

    python CSRF跨站请求伪造 <!DOCTYPE html> <html lang="en"> <head> <meta chars ...

  2. Django之CSRF跨站请求伪造(老掉牙的钓鱼网站模拟)

    首先这是一个测试的代码 请先在setting页面进行下面操作 注释完成后,开始模拟钓鱼网站的跨站请求伪造操作: 前端代码: <!DOCTYPE html> <html lang=&q ...

  3. ajax向Django前后端提交请求和CSRF跨站请求伪造

    1.ajax登录示例 urls.py from django.conf.urls import url from django.contrib import admin from app01 impo ...

  4. python 全栈开发,Day87(ajax登录示例,CSRF跨站请求伪造,Django的中间件,自定义分页)

    一.ajax登录示例 新建项目login_ajax 修改urls.py,增加路径 from app01 import views urlpatterns = [ path('admin/', admi ...

  5. 第三百一十五节,Django框架,CSRF跨站请求伪造

    第三百一十五节,Django框架,CSRF跨站请求伪造  全局CSRF 如果要启用防止CSRF跨站请求伪造,就需要在中间件开启CSRF #中间件 MIDDLEWARE = [ 'django.midd ...

  6. Django中的CSRF(跨站请求伪造)

    Django中的CSRF(跨站请求伪造) Django CSRF  什么是CSFR 即跨站请求伪装,就是通常所说的钓鱼网站. 钓鱼网站的页面和正经网站的页面对浏览器来说有什么区别? (页面是怎么来的? ...

  7. Django框架 之 基于Ajax中csrf跨站请求伪造

    Django框架 之 基于Ajax中csrf跨站请求伪造 ajax中csrf跨站请求伪造 方式一 1 2 3 $.ajaxSetup({     data: {csrfmiddlewaretoken: ...

  8. 十三 Django框架,CSRF跨站请求伪造

     全局CSRF 如果要启用防止CSRF跨站请求伪造,就需要在中间件开启CSRF #中间件 MIDDLEWARE = [ 'django.middleware.security.SecurityMidd ...

  9. Web框架之Django_09 重要组件(Django中间件、csrf跨站请求伪造)

    摘要 Django中间件 csrf跨站请求伪造 一.Django中间件: 什么是中间件? 官方的说法:中间件是一个用来处理Django的请求和响应的框架级别的钩子.它是一个轻量.低级别的插件系统,用于 ...

  10. django上课笔记3-ORM补充-CSRF (跨站请求伪造)

    一.ORM补充 ORM操作三大难点: 正向操作反向操作连表 其它基本操作(包含F Q extra) 性能相关的操作 class UserInfo(models.Model): uid = models ...

随机推荐

  1. [转]关于PreparedStatement.addBatch()方法

    Statement和PreparedStatement的区别就不多废话了,直接说PreparedStatement最重要的addbatch()结构的使用. 1.建立链接,(打电话拨号 ) Connec ...

  2. Android开发笔记——视频录制播放常见问题

    本文分享自己在视频录制播放过程中遇到的一些问题,主要包括: 视频录制流程 视频预览及SurfaceHolder 视频清晰度及文件大小 视频文件旋转 一.视频录制流程 以微信为例,其录制触发为按下(住) ...

  3. Appium+python的单元测试框架unittest(3)——discover(转)

    (原文:https://www.cnblogs.com/fancy0158/p/10047906.html) TestSuite套件可以添加很多个用例后运行,但是每个用例都需要调用addTest()函 ...

  4. 一、初识 Django

    一.引子 Django最初设计用于具有快速开发需求的新闻类站点,目的是要实现简单快捷的网站开发! 从好的方面来看,Web 开发激动人心且富于创造性:从另一面来看,它却是份繁琐而令人生厌的工作.通过减少 ...

  5. MySql面试题(持续更新)

    1. 左连接,右连接,内连接的概念. 左连接:以左表为主,保留左表的所有数据,并且依次拿每行数据去匹配右表所有行,如果没匹配的,右边表的数据为null. 右连接:以右表为主,保留右表的所有数据,并且依 ...

  6. 高可用Kubernetes集群-3. etcd高可用集群

    五.部署高可用etcd集群 etcd是key-value存储(同zookeeper),在整个kubernetes集群中处于中心数据库地位,以集群的方式部署,可有效避免单点故障. 这里采用静态配置的方式 ...

  7. 【第八章】MySQL数据库备份—逻辑备份

    一.数据库备份 1.命令简介: # mysqldump -h 服务器 -u用户名 -p密码 数据库名 > 备份文件.sql1)关于数据库名: -A, --all-databases       ...

  8. Ubuntu系统下在PyCharm里用virtualenv集成TensorFlow

    我的系统环境 Ubuntu 18.04 Python3.6 PyCharm 2018.3.2 community(免费版) Java 1.8 安装前准备 由于众所周知的原因,安装中需要下载大量包,尽量 ...

  9. RIGHT-BICEP单元测试——“二柱子四则运算升级版”

    RIGHT-BICEP单元测试 ——“二柱子四则运算升级版” ”单元测试“这对于我们来说是一个全新的专业含义,在上了软件工程这门课,并当堂编写了简单的"求一组数中的最大值"函数的单 ...

  10. C++Primer第五版——习题答案和解析

    感谢原文博主的分享:https://blog.csdn.net/misayaaaaa/article/details/53786215 新手入门必看的书.知识是一个系统化并且相互关联的体系,零散的东西 ...