csrf跨站请求伪造
模拟钓鱼网站
本质搭建一个跟正常网站一模一样的页面
用户在该页面上完成转账功能
转账的请求确实是朝着正常网站的服务端提交
唯一不同的在于收款账户人不同
给用户书写form表单 对方账户的input没有name属性
你自己悄悄提前写好了一个具有默认的并且是隐藏的具有name属性的input
此时为了防止csrf跨站请求伪造(钓鱼网站),可以给form表单内写一个 {% csrf_token %}
csrf具体做了什么
在渲染模板时,django会把 {% csrf_token %} 替换成一个<input type="hidden", name='csrfmiddlewaretoken' value=服务器随机生成的token>元素。在提交表单的时候,会把这个token给提交上去
Ajax如何通过csrf校验
第一种方式,自己手动获取
{#data:{'username':'kai','csrfmiddlewaretoken':$('input[name="csrfmiddlewaretoken"]').val()},#}
第二种方式 利用模板语法
{#data:{'username':'kai','csrfmiddlewaretoken':'{{ csrf_token }}'},#}
第三种 通用方式 引入外部js文件 官网提供的方式
<button id="d1">发送Ajax请求</button>1 {% load static %} <script src="{% static 'myset.js' %}"></script> <script> $('#d1').click(function () { $.ajax({ url: '', type: 'post', {# 第一种,自己手动导入 #} {#data: {'username':'jason','csrfmiddlewaretoken':$('input[name="csrfmiddlewaretoken"]').val()} 第二种#} {# 第二种,利用模板语法 #} {#data: {'username':'jason','csrfmiddlewaretoken':'{{ csrf_token }}'}#} {# 第三种,通用方式,引入外部js文件 #} data: {'username': 'kai'} success: function (data) { alert(data) } }) }) </script>
在static文件夹内创建一个myset.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); } } });
csrf相关装饰器
当我们网站整体都校验csrf的时候 我想让某几个视图函数不校验 @csrf_exempt
当我们网站整体都不校验csrf的时候 我想让某几个视图函数校验 @csrf_protect
from django.views.decorators.csrf import csrf_exempt, csrf_protect from django.views import View from django.utils.decorators import method_decorator # @method_decorator(csrf_protect,name='post') # 第二种在类上面指名道姓的给类中某个方法装 # @method_decorator(csrf_exempt,name='post') # csrf_exempt 第二种方式不行 @method_decorator(csrf_exempt,name='dispatch') # 可以!!! class MyHome(View): # APIView # @method_decorator(csrf_protect) # 第三种在dispatch什么 类中所有的方法都装 # @method_decorator(csrf_exempt) # csrf_exempt 第三种方式可以 def dispatch(self, request, *args, **kwargs): return super().dispatch(request,*args,**kwargs) def get(self,request): return HttpResponse('get') # @method_decorator(csrf_protect) # 第一种方式,在方法上面添加 # @method_decorator(csrf_exempt) # csrf_exempt 第一种方式不行 def post(self,request): return HttpResponse('post')
给CBV加装饰器 推荐你使用模块method_decorator
我们自己写的装饰器和csrf_protect用法一致
唯独csrf_exempt是一个特例 只能给dispatch方法装