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方法装

 posted on 2020-01-14 21:06  Rannie`  阅读(222)  评论(0编辑  收藏  举报
去除动画
找回动画