Django自身安全机制

XSS攻击

什么是XSS攻击

XSS是一种经常出现在web应用中的计算机安全漏洞,它允许恶意web用户将代码植入到提供给其它用户使用的页面中。比如这些代码包括HTML代码和客户端脚本。攻击者利用XSS漏洞旁路掉访问控制——例如 同源策略(same origin policy)。这种类型的漏洞由于被黑客用来编写危害性更大的 网络钓鱼(Phishing)攻击而变得广为人知。对于 跨站脚本攻击,黑客界共识是:跨站脚本攻击是新型的“ 缓冲区溢出攻击“,而JavaScript是新型的“ShellCode”。

实施XSS攻击需要具备两个条件:

一、需要向web页面注入恶意代码;

二、这些恶意代码能够被浏览器成功的执行。

解决办法:

  1、一种方法是在表单提交或者url参数传递前,对需要的参数进行过滤。
  2、在后台对从数据库获取的字符串数据进行过滤,判断关键字。
  3、设置安全机制。
  django框架:内部机制默认阻止了。它会判定传入的字符串是不安全的,就不会渲染而以字符串的形式显示。如果手贱写了safe,那就危险了,若想使用safe,那就必须在后台对要渲染的字符串做过滤了。所以在开发的时候,一定要慎用安全机制。尤其是对用户可以提交的并能渲染的内容!!!

- 示例:

1 1 <!DOCTYPE html> 2 2 <html lang="en"> 3 3 <head> 4 4 <meta charset="UTF-8"> 5 5 <title></title> 6 6 </head> 7 7 <body> 8 8 <form method="POST" action="/comment/"> 9 9 <h4>评论</h4> 1010 <input type="text" name="content"/> 1111 <input type="submit" value="提交" />{{ error }} 1212 </form> 1313 </body> 1414 </html>

评论提交页面

1 1 <!DOCTYPE html> 2 2 <html lang="en"> 3 3 <head> 4 4 <meta charset="UTF-8"> 5 5 <title></title> 6 6 </head> 7 7 <body> 8 8 <h1>评论内容</h1> 9 9 {% for item in msg %} 1010 <div>{{ item|safe }}</div> 1111 {% endfor %} 1212 </body> 1313 </html>

评论显示页面

1 1 from django.shortcuts import render 2 2 msg = [] 3 3 def comment(request): 4 4 if request.method == "GET": 5 5 return render(request,'comment.html') 6 6 else: 7 7 v = request.POST.get('content') 8 8 if "script" in v: 9 9 return render(request,'comment.html',{'error': '小比崽子还黑我'}) 1010 else: 1111 msg.append(v) 1212 return render(request,'comment.html') 1313 1414 def index(request): 1515 return render(request,'index.html',{'msg':msg}) 1616 1717 def test(request): 1818 from django.utils.safestring import mark_safe 1919 temp = "<a href='http://www.baidu.com'>百度</a>" 2020 newtemp = mark_safe(temp) 2121 return render(request,'test.html',{'temp':newtemp}

后台处理

CSRF跨站请求伪造

什么是 CSRF

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

csrf攻击过程

1.用户C打开浏览器,访问受信任网站A,输入用户名和密码请求登录网站A;

2.在用户信息通过验证后,网站A产生Cookie信息并返回给浏览器,此时用户登录网站A成功,可以正常发送请求到网站A;

3.用户未退出网站A之前,在同一浏览器中,打开一个TAB页访问网站B;

4.网站B接收到用户请求后,返回一些攻击性代码,并发出一个请求要求访问第三方站点A;

5.浏览器在接收到这些攻击性代码后,根据网站B的请求,在用户不知情的情况下携带Cookie信息,向网站A发出请求。网站A并不知道该请求其实是由B发起的,所以会根据用户C的Cookie信息以C的权限处理该请求,导致来自网站B的恶意代码被执行。

csrf的攻击之所以会成功是因为服务器端身份验证机制可以通过Cookie保证一个请求是来自于某个用户的浏览器,但无法保证该请求是用户允许的。因此,预防csrf攻击简单可行的方法就是在客户端网页上添加随机数,在服务器端进行随机数验证,以确保该请求是用户允许的。Django也是通过这个方法来防御csrf攻击的。

在django防御csrf攻击

原理

在客户端页面上添加csrftoken, 服务器端进行验证,服务器端验证的工作通过'django.middleware.csrf.CsrfViewMiddleware'这个中间层来完成。在django当中防御csrf攻击的方式有两种, 1.在表单当中附加csrftoken 2.通过request请求中添加X-CSRFToken请求头。注意:Django默认对所有的POST请求都进行csrftoken验证,若验证失败则403错误侍候。

在表单中附加csrftoken

后端

1 1 from django.shortcuts import render 2 2 from django.template.context_processors import csrf 3 3 4 4 def ajax_demo(request): 5 5 # csrf(request)构造出{‘csrf_token’: token} 6 6 return render(request, 'post_demo.html', csrf(request))

前端

1 1 $('#send').click(function(){ 2 2 3 3 $.ajax({ 4 4 type: 'POST', 5 5 url:'{% url 'ajax:post_data' %}', 6 6 data: { 7 7 username: $('#username').val(), 8 8 content: $('#content').val(), 9 9 'csrfmiddlewaretoken': '{{ csrf_token }}' 关键点 1010 }, 1111 dataType: 'json', 1212 success: function(data){ 1313 1414 }, 1515 error: function(){ 1616 1717 } 1818 1919 }); 2020 });

View Code

通过request请求中添加X-CSRFToken请求头

后端

该方式需要借助于Cookie传递csrftoken, 设置Cookie的方式有两种。ps:经测试即便什么都不做,也会设置Cookie,不过官方文档说,不保证每次都有效

1.表单中添加{%csrf_token%}这个模板标签

11 <form id="comment_form" action="#"></form> 22 {% csrf_token %} 就是这个 33 <p>姓名: <input type="text" name="useranme" id="username"></p> 44 <p>内容: <textarea name="content" id="content" rows="5" cols="30"></textarea></p> 55 <p><input type="button", id="send" value="提交"></p>

2.ensure_csrf_cookie装饰器

11 from django.shortcuts import render 22 from django.views.decorators.csrf import ensure_csrf_cookie 33 44 @ensure_csrf_cookie 55 def ajax_demo(request): 66 return render(request, 'ajax_demo.html')

前端
前端要做的事情,在进行post提交时,获取Cookie当中的csrftoken并在请求中添加X-CSRFToken请求头, 该请求头的数据就是csrftoken。通过$.ajaxSetup方法设置AJAX请求的默认参数选项, 在每次ajax的POST请求时,添加X-CSRFToken请求头

1 1 <script type="text/javascript"> 2 2 $(function(){ 3 3 4 4 function getCookie(name) { 5 5 var cookieValue = null; 6 6 if (document.cookie && document.cookie != '') { 7 7 var cookies = document.cookie.split(';'); 8 8 for (var i = 0; i < cookies.length; i++) { 9 9 var cookie = jQuery.trim(cookies[i]); 1010 // Does this cookie string begin with the name we want? 1111 if (cookie.substring(0, name.length + 1) == (name + '=')) { 1212 cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); 1313 break; 1414 } 1515 } 1616 } 1717 return cookieValue; 1818 } 1919 2020 <!--获取csrftoken--> 2121 var csrftoken = getCookie('csrftoken'); 2222 console.log(csrftoken); 2323 2424 //Ajax call 2525 function csrfSafeMethod(method) { 2626 // these HTTP methods do not require CSRF protection 2727 return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); 2828 } 2929 3030 $.ajaxSetup({ 3131 crossDomain: false, // obviates need for sameOrigin test 3232 //请求前触发 3333 beforeSend: function(xhr, settings) { 3434 if (!csrfSafeMethod(settings.type)) { 3535 xhr.setRequestHeader("X-CSRFToken", csrftoken); 3636 } 3737 } 3838 }); 3939 4040 $('#send').click(function(){ 4141 console.log($("#comment_form").serialize()); 4242 4343 $.ajax({ 4444 type: 'POST', 4545 url:'{% url 'ajax:post_data' %}', 4646 data: { 4747 username: $('#username').val(), 4848 content: $('#content').val(), 4949 //'csrfmiddlewaretoken': '{{ csrf_token }}' 5050 }, 5151 dataType: 'json', 5252 success: function(data){ 5353 5454 5555 }, 5656 error: function(){ 5757 5858 } 5959 6060 }); 6161 }); 6262 6363 6464 }); 6565 </script>

取消csrftoken验证

通过csrf_exempt, 来取消csrftoken验证,方式有两种。
1 .在视图函数当中添加csrf_exempt装饰器

11 from django.views.decorators.csrf import csrf_exempt 22 33 @csrf_exempt 44 def post_data(request): 55 pass

2 .在urlconf当中

11 from django.views.decorators.csrf import csrf_exempt 22 urlpatterns = [ 33 url(r'^post/get_data/$', csrf_exempt(post_data), name='post_data'), 44 55 ]

django csrf注意点:

**注意一定注意:ajax POST提交的时候,csrf-token 随机字符串 直接放在data数据中的方式为:**data:{csrfmiddlewaretoken:"{{ csrf_token }}"}

  若是导入自己写的JS文件,那上述方法就不能获取到Django后台发送的随机字符串,而是需要利用上面介绍的两种方式获取(页面写上{% csrf_token %},通过隐藏的input标签取value值写在POST提交的data数据中;或是从cookie中获取,写在头文件中。)

使用django框架时: 
  每次初始化一个项目时都要看看 django.middleware.csrf.CsrfViewMiddleware 这个中间件
  每次在模板里写 form 时都需要加一个 {% csrf_token %} tag
  每次发 ajax POST 请求,都需要加一个 X_CSRFTOKEN 的 header
流程:
  用户第一次访问页面,肯定是get请求,此时服务端就会给客户端发送一段随机字符串的数据,当客户提交数据的时候,常在POST请求中带回,就会发送随机字符串给服务端(上一次请求获取的数据)用于验证。
  服务端给客户端发送的随机字符串作为一种安全机制,客户端往服务端发送请求时再携带回来,用于匹配认证。
  可以从form表单中接收,也可以在cookies中查看,注意:这两个的随机字符串是不同的!
  如果开启了csrf认证,后台没有拿到对应的字符串的话就会报错---> 403

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )