跨站請求僞造(csrf)

正規的網站的操做

  1. 正規網站在返回給用戶含有post請求的頁面 都附帶了一個隨機的字符串
  2. 而後下一次用戶在提交post請求的時候 會先校驗該隨機字符串是否存在並判斷是否一致
  3. 詳情參考解決釣魚網站的策略

跨站請求僞造(csrf) 釣魚網站

​ 就相似於你搭建了一個跟銀行如出一轍的web頁面
​ 用戶在你的網站轉帳的時候輸入用戶名 密碼 對方帳戶
​ 銀行裏面的錢確實少了 可是發現收款人變了前端

最簡單的原理

  1. 你寫的form表單中 用戶的用戶名 密碼都會真實的提交給銀行後臺
  2. 可是收款人的帳戶卻不是用戶填的 你暴露給用戶的是一個沒有name屬性的input框
  3. 你本身提早寫好了一個隱藏的帶有name和value的input框

真正的網站

前端python

<h1>真正的網站</h1>

<form action="" method="post">
    <p>username:<input type="text" name="username"></p>
    <p>target_username:<input type="text" name="target_username"> </p>
    <p>money:<input type="text" name="money"></p>
    <input type="submit">
</form>

後端web

def transfer(request):#轉帳
    if request.method=="POST":
        username = request.POST.get('username')
        target_username = request.POST.get('target_username')
        money = request.POST.get('money')
        print('%s給%s轉了%s錢'%(username,target_username,money))
    return render(request,'formm.html')

釣魚網站

前端ajax

<h1>釣魚的網站</h1>
<form action="http://127.0.0.1:8000/transfer/" method="post">
    <p>username:<input type="text" name="username"></p>
    <input type="text" name="target_username" value="sky" style="display: none">

    <p>target_username:<input type="text"></p>
    <p>money:<input type="text" name="money"></p>
    <input type="submit">
</form>

後端django

def transfer(request):
    return render(request,'taansfer.html')

解決釣魚網站的策略

  1. 只要是用戶想要提交post請求的頁面 我在返回給用戶的時候就提早設置好一個隨機字符串
  2. 當用戶提交post請求的時候 我會自動先取查找是否有該隨機字符串
  3. 若是有 正常提交
  4. 若是沒有 直接報403

form表單方法1

{% csrf_token %} 給出一個隨機字符串,用來進行校驗後端

<h1>真正的網站</h1>

<form action="" method="post">
    {% csrf_token %}
    <p>username:<input type="text" name="username"></p>
    <p>target_username:<input type="text" name="target_username"> </p>
    <p>money:<input type="text" name="money"></p>
    <input type="submit">
</form>

ajax方法1

第一種 本身再頁面上先經過{% csrf_token %}獲取到隨機字符串 而後利用標籤查找cookie

data{'username':'jason','csrfmiddlewaretoken':$('[name="csrfmiddlewaretoken"]').val()},post

<h1>真正的網站</h1>

<form action="" method="post">
    {% csrf_token %}
    <p>username:<input type="text" name="username"></p>
    <p>target_username:<input type="text" name="target_username"></p>
    <p>money:<input type="text" name="money"></p>
</form>
<button id="b1">發ajax</button>
<script>
    $('#b1').click(function () {
        $.ajax({
            url: "",
            type: "post",
            data: {"username": "sky", "csrfmiddlewaretoken": $('[name="csrfmiddlewaretoken"]').val()},
            success: function (data) {
                alert(data)

            }
        })

    })
</script>

ajax方法2

第二種data:{'username':'jason','csrfmiddlewaretoken':'{{ csrf_token }}'},網站

<h1>真正的網站</h1>

<form action="" method="post">
    {% csrf_token %}
    <p>username:<input type="text" name="username"></p>
    <p>target_username:<input type="text" name="target_username"></p>
    <p>money:<input type="text" name="money"></p>
</form>
<button id="b1">發ajax</button>
<script>
    $('#b1').click(function () {
        $.ajax({
            url: "",
            type: "post",
            data: {"username": "sky", "csrfmiddlewaretoken": "{{csrf_token }}"},
            success: function (data) {
                alert(data)

            }
        })

    })
</script>

ajax方法3

前端,導入下面的js

<h1>真正的網站</h1>

<form action="" method="post">
    {% csrf_token %}
    <p>username:<input type="text" name="username"></p>
    <p>target_username:<input type="text" name="target_username"></p>
    <p>money:<input type="text" name="money"></p>
</form>
<button id="b1">發ajax</button>
<script src="/static/setpe.js"></script>
<script>
    $('#b1').click(function () {
        $.ajax({
            url: "",
            type: "post",
            data: {"username": "sky"},
            success: function (data) {
                alert(data)

            }
        })

    })
</script>

第三種
拷貝下面js文件,新建文件夾static,而後靜態文件配置,而後導入前端文件

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

將上面的django的靜態文件中,在html頁面上經過導入該文件便可自動幫咱們解決ajax提交post數據時校驗csrf_token的問題,(導入該配置文件以前,須要先導入jQuery,由於這個配置文件內的內容是基於jQuery來實現的)

更多細節詳見:Djagno官方文檔中關於CSRF的內容

校驗指定的請求

csrf_exempt 只有兩種裝飾的方式

from django.views.decorators.csrf import csrf_exempt, csrf_protect
#csrf_exempt 不校驗
# csrf_protect 校驗

第一種

from django.views.decorators.csrf import csrf_exempt, csrf_protect
from django.utils.decorators import method_decorator
@csrf_exempt
def exem(request):
    return HttpResponse('exempt')

@csrf_protect
def pro(request):
    return HttpResponse('pro')

CBV裝飾器

除了csrf_exempt以外 全部的其餘裝飾器 在CBV上面都有三種方式

方式1

命名@method_decorator(csrf_exempt,name='dispatch')

from django.views.decorators.csrf import csrf_exempt, csrf_protect
from django.utils.decorators import method_decorator
from django.views import View
# 第一種
# @method_decorator(csrf_exempt,name='dispatch')
class MyCsrf(View):
    @method_decorator(csrf_protect)
    def dispatch(self, request, *args, **kwargs):
        return super().dispatch(request,*args,**kwargs)
    def get(self,request):
        return HttpResponse('hahaha')

    @method_decorator(csrf_protect)
    def post(self,request):
        return HttpResponse('post')

方式2

@method_decorator(csrf_protect)

from django.views.decorators.csrf import csrf_exempt, csrf_protect
from django.utils.decorators import method_decorator
from django.views import View

class MyCsrf(View):
    @method_decorator(csrf_protect)
    def dispatch(self, request, *args, **kwargs):
        return super().dispatch(request,*args,**kwargs)
    def get(self,request):
        return HttpResponse('hahaha')

    @method_decorator(csrf_protect)
    def post(self,request):
        return HttpResponse('post')
相關文章
相關標籤/搜索