Django之csrf跨站请求
一:csrf基础简介
(1)产生背景:
(1)钓鱼网站
(1)通过制作一个跟正儿八经的网站一模一样的页面,骗取用户输入信息 转账交易从而做手脚
(2)转账交易的请求确确实实是发给了中国银行,账户的钱也是确确实实少了
(3)唯一不一样的地方在于收款人账户不对
例如:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<form action="/lll/" method="post"> <p>本人用户名:<input type="text" name="username"></p> <p>转账金额:<input type="text" name="money"></p> <p>对方账户:<input type="text" name="target_user"></p> <input type="submit"> </form>
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<form action="http://127.0.0.1:8000/transfer/" method="post"> <p>本人用户名:<input type="text" name="username"></p> <p>转账金额:<input type="text" name="money"></p> <p>对方账户:<input type="text"></p> <input type="text" name="target_user" value="jason" style="display: none"> <input type="submit"> </form>
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
def transfer(request): if request.method == 'POST': username = request.POST.get('username') money = request.POST.get('money') target_user = request.POST.get('target_user') print('%s 给 %s 转了 %s元'%(username,target_user,money)) return render(request,'t.html')
PS:
(1):其在给目标用户的输入框 偷偷写一个name和value属性的input框 value值就是目标用户值
(2)解决办法:
(1)当用户发送请求的时候的 服务端会给客户端添加一个随机字符串
(2)请求到来的时候 会对比随机字符串 如果不一致 直接拒绝
{% csrf_token %}
PS:
(1)不同浏览器的随机字符串不一样
(2)每次访问请求随机字符串也不一样
二:ajax提交数据
(1)方式一:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# 方法为开启 <form action="" method="post"> <button id="d1">ajax提交</button> </form> <script> $('#d1').click(function () { $.ajax({ url:'', 'type':'post', data:{'name':'SR'}, success:function (data) { alert(data) } }) }) </script>
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<form action="" method="post"> <button id="d1">ajax提交</button> {% csrf_token %} </form> <script> $('#d1').click(function () { $.ajax({ url:'', 'type':'post', data:{'name':'SR','csrfmiddlewaretoken':$('[name=csrfmiddlewaretoken]').val()}, // 获取到用户input框信息 success:function (data) { alert(data) } }) }) </script>
PS:此时已经可以正常访问
(2)方法二:直接属性{{crsf_token}}
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<form action="" method="post"> <button id="d1">ajax提交</button> {% csrf_token %} </form> <script> $('#d1').click(function () { $.ajax({ url:'', 'type':'post', data:{'name':'SR','csrfmiddlewaretoken':'{{ csrf_token }}'}, // 通过获取变量的形式 success:function (data) { alert(data) } }) }) </script>
(3)方式三:外部导入js文件
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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); } } });
三:FBV装饰器登录
csrf_exempt
1.当你网站全局都需要校验csrf的时候 有几个不需要校验该如何处理
例如:
from django.views.decorators.csrf import csrf_exempt,csrf_protect def index(request): return HttpResponse('不需要被校验') @csrf_protect def transfer(request): return HttpResponse('此时就你需要被校验')
csrf_protect
2.当你网站全局不校验csrf的时候 有几个需要校验又该如何处理
from django.views.decorators.csrf import csrf_exempt,csrf_protect @csrf_exempt def index(request): return HttpResponse('不需要被校验') def transfer(request): return HttpResponse('此时就你需要被校验')
四:CBV装饰器
(1)csrf_protect
from django.utils.decorators import method_decorator # 第一种方式 # @method_decorator(csrf_protect,name='post') # 有效的 class MyView(View):
# 第三种方式 # @method_decorator(csrf_protect) def dispatch(self, request, *args, **kwargs): res = super().dispatch(request, *args, **kwargs) return res
def get(self,request): return HttpResponse('get') # 第二种方式 # @method_decorator(csrf_protect) # 有效的 def post(self,request): return HttpResponse('post')
PS:
(1)直接在全局给某个字段做装饰
(2)在局部给某个想要装饰的字段做装饰
(3)在dispatch方法做装饰
(2)
@method_decorator(csrf_exempt, name='dispatch') # 第二种可以不校验的方式 class MyView(View): # @method_decorator(csrf_exempt) # 第一种可以不校验的方式 def dispatch(self, request, *args, **kwargs): res = super().dispatch(request, *args, **kwargs) return res def get(self, request): return HttpResponse('g
PS:
(1)局部给disp做装饰
(2)全局给dispatch做装饰