Django之csrf跨站请求

一:csrf基础简介

(1)产生背景:

(1)钓鱼网站

  (1)通过制作一个跟正儿八经的网站一模一样的页面,骗取用户输入信息 转账交易从而做手脚
  (2)转账交易的请求确确实实是发给了中国银行,账户的钱也是确确实实少了
  (3)唯一不一样的地方在于收款人账户不对

例如:

<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>
正常网站
<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>
钓鱼网站
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)方式一:

# 方法为开启

<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>
未使用方法之前

 <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}}

    <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文件

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);
        }
    }
});
        
                    
JS文件

三: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做装饰

posted @ 2019-09-25 22:29  SR丶  阅读(147)  评论(0编辑  收藏  举报