1. 程式人生 > 其它 >39 django之csrf

39 django之csrf

django為使用者實現防止跨站請求偽造的功能,通過中介軟體 django.middleware.csrf.CsrfViewMiddleware 來完成

1 csrf跨站請求偽造校驗

網站在給使用者返回一個具有提交資料功能頁面的時候會給這個頁面加一個唯一標識
當這個頁面朝後端傳送post請求的時候
後端會先校驗唯一標識,如果唯一標識不對直接拒絕(403 forbbiden)
如果成功則正常執行

2 form表單如何符合校驗

{%csrf_token%}

<form action="" method="post">
    {% csrf_token %}
    <p>username:<input type="
text" name="username" class="form-control"></p> <p>password:<input type="text" name="password" class="form-control"></p> <input type="submit" class="btn btn-success"> </form>

3 ajax如何符合校驗

第一種 利用標籤查詢獲取頁面上的隨機字串

放在data裡:'csrfmiddlewaretoken':$('[name=csrfmiddlewaretoken]').val()

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css
" rel="stylesheet"> <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script> </head> <body> <h1 class="text-center">登入</h1> <form action="" method="post"> <p>username:<input type="text" name="username" class="form-control"></p> <p>password:<input type="text" name="password" class="form-control"></p> </form> <button id="d1">點我</button> <script> $('#d1').click(function (){ $.ajax({ url:'', type:'post', data:{"username":'dzg','csrfmiddlewaretoken':$('[name=csrfmiddlewaretoken]').val()}, success:function (){ } }) }) </script> </body> </html>

第二種 利用模版語法提供的快捷書寫

放在data裡:'csrfmiddlewaretoken':'{{ csrf_token }}'

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>

</head>
<body>
<h1 class="text-center">登入</h1>
<form action="" method="post">
    <p>username:<input type="text" name="username" class="form-control"></p>
    <p>password:<input type="text" name="password" class="form-control"></p>

</form>

<button id="d1">點我</button>

<script>
    $('#d1').click(function (){
        $.ajax({
            url:'',
            type:'post',
            data:{"username":'dzg','csrfmiddlewaretoken':'{{ csrf_token }}'},
            success:function (){

            }
        })
    })
</script>

</body>
</html>

第三種 直接拷貝js程式碼並應用到自己的html頁面上即可 先建一個static資料夾,再建js資料夾,建任意的js檔案

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

login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>
<h1 class="text-center">登入</h1>
<form action="" method="post">
    <p>username:<input type="text" name="username" class="form-control"></p>
    <p>password:<input type="text" name="password" class="form-control"></p>

</form>

<button id="d1">點我</button>
{% load static %}
<script src="{% static 'js/mycsrf.js' %}"></script>
<script>
    $('#d1').click(function (){
        $.ajax({
            url:'',
            type:'post',
            data:{"username":'dzg',},
            success:function (){

            }
        })
    })
</script>

</body>
</html>

4csrf相關裝飾器

csrf_protect 需要校驗
針對csrf_protect符合我們之前所學的裝飾器的三種玩法
csrf_exempt 忽視校驗
針對csrf_exempt只能給dispatch方法加才有效

4.1 簡單使用

# @csrf_exempt
# @csrf_protect
def transfer(request):
    if request.method == 'POST':
       return HttpResponse('666')
    return render(request,'login.html')

4.2

網站整體都不校驗csrf,就單單幾個檢視函式需要校驗
網站整體都校驗csrf,就單單幾個檢視函式不校驗

from django.views import View

# @method_decorator(csrf_protect,name='post')  # 針對csrf_protect 第二種方式可以
# @method_decorator(csrf_exempt,name='post')  # 針對csrf_exempt 第二種方式不可以
@method_decorator(csrf_exempt,name='dispatch')
class MyCsrfToken(View):
    # @method_decorator(csrf_protect)  # 針對csrf_protect 第三種方式可以
    # @method_decorator(csrf_exempt)  # 針對csrf_exempt 第三種方式可以
    def dispatch(self, request, *args, **kwargs):
        return super(MyCsrfToken, self).dispatch(request,*args,**kwargs)

    def get(self,request):
        return HttpResponse('get')

    # @method_decorator(csrf_protect)  # 針對csrf_protect 第一種方式可以
    # @method_decorator(csrf_exempt)  # 針對csrf_exempt 第一種方式不可以
    def post(self,request):
        return HttpResponse('post')