39 django之csrf
django为用户实现防止跨站请求伪造的功能,通过中间件 django.middleware.csrf.CsrfViewMiddleware 来完成
1 csrf跨站请求伪造校验
在渲染form表单的时候,给一个随机的标识,下次提交的时候,后天验证该标识,如果不一样,说明不是我们的页面,直接403, 否则,验证通过
网站在给用户返回一个具有提交数据功能页面的时候会给这个页面加一个唯一标识 当这个页面朝后端发送post请求的时候 后端会先校验唯一标识,如果唯一标识不对直接拒绝(403 forbbiden) 如果成功则正常执行
2 form表单如何符合校验
{% csrf_token %} #生成唯一标识
<form action="" method="post"> {% csrf_token %} <p>username:<input type="text" name="username" class="form-control"></p> <p>password:<input type="text" name="password" class="form-control"></p> <input type="submit" class="btn btn-success"> </form>
3 ajax如何符合校验
第一种 利用标签查找获取页面上的随机字符串
放在data里:'csrfmiddlewaretoken':$('[name=csrfmiddlewaretoken]').val()
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script> <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet"> <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script> </head> <body> <h1 class="text-center">登录</h1> <form action="" method="post"> <p>username:<input type="text" name="username" class="form-control"></p> <p>password:<input type="text" name="password" class="form-control"></p> </form> <button id="d1">点我</button> <script> $('#d1').click(function (){ $.ajax({ url:'', type:'post', data:{"username":'dzg','csrfmiddlewaretoken':$('[name=csrfmiddlewaretoken]').val()}, success:function (){ } }) }) </script> </body> </html>
第二种 利用模版语法提供的快捷书写
放在data里:'csrfmiddlewaretoken':'{{ csrf_token }}'
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script> <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet"> <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script> </head> <body> <h1 class="text-center">登录</h1> <form action="" method="post"> <p>username:<input type="text" name="username" class="form-control"></p> <p>password:<input type="text" name="password" class="form-control"></p> </form> <button id="d1">点我</button> <script> $('#d1').click(function (){ $.ajax({ url:'', type:'post', data:{"username":'dzg','csrfmiddlewaretoken':'{{ csrf_token }}'}, success:function (){ } }) }) </script> </body> </html>
第三种 直接拷贝js代码并应用到自己的html页面上即可 先建一个static文件夹,再建js文件夹,建任意的js文件
mycsrf.js
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 = 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; } var csrftoken = getCookie('csrftoken'); function csrfSafeMethod(method) { // these HTTP methods do not require CSRF protection return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); } $.ajaxSetup({ beforeSend: function (xhr, settings) { if (!csrfSafeMethod(settings.type) && !this.crossDomain) { xhr.setRequestHeader("X-CSRFToken", csrftoken); } } });
login.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script> <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet"> <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script> </head> <body> <h1 class="text-center">登录</h1> <form action="" method="post"> <p>username:<input type="text" name="username" class="form-control"></p> <p>password:<input type="text" name="password" class="form-control"></p> </form> <button id="d1">点我</button> {% load static %} <script src="{% static 'js/mycsrf.js' %}"></script> <script> $('#d1').click(function (){ $.ajax({ url:'', type:'post', data:{"username":'dzg',}, success:function (){ } }) }) </script> </body> </html>
4 csrf相关装饰器
csrf_protect 需要校验
针对csrf_protect符合我们之前所学的装饰器的三种玩法
csrf_exempt 忽视校验
针对csrf_exempt只能给dispatch方法加才有效
4.1 简单使用
# @csrf_exempt # @csrf_protect def transfer(request): if request.method == 'POST': return HttpResponse('666') return render(request,'login.html')
4.2
网站整体都不校验csrf,就单单几个视图函数需要校验
网站整体都校验csrf,就单单几个视图函数不校验
from django.views import View # @method_decorator(csrf_protect,name='post') # 针对csrf_protect 第二种方式可以 # @method_decorator(csrf_exempt,name='post') # 针对csrf_exempt 第二种方式不可以 @method_decorator(csrf_exempt,name='dispatch') class MyCsrfToken(View): # @method_decorator(csrf_protect) # 针对csrf_protect 第三种方式可以 # @method_decorator(csrf_exempt) # 针对csrf_exempt 第三种方式可以 def dispatch(self, request, *args, **kwargs): return super(MyCsrfToken, self).dispatch(request,*args,**kwargs) def get(self,request): return HttpResponse('get') # @method_decorator(csrf_protect) # 针对csrf_protect 第一种方式可以 # @method_decorator(csrf_exempt) # 针对csrf_exempt 第一种方式不可以 def post(self,request): return HttpResponse('post')