Django信息安全相關之CSRF和XSS

什麼是xss攻擊

xss攻擊:黑客把惡意的JS腳本提交到後端,後端把惡意腳本渲染顯示出來    html

什麼是CSRF?

一、你登陸建行官網後 你的瀏覽器就保存了建行網站的cokie,(若是不關閉這個頁面cookie一直生效,就能夠發送任何請求)專門在cappron試了一下;jquery

二、與此同時你 點了其餘惡意頁面(CSRF攻擊的條件)git

三、這個頁面攜帶着你的cokie 僞造你 向到招商銀行提交 一個轉帳form表單你就傻逼了!github

(問題關鍵:登陸某網站以後有了cokie,就能夠發送任何請求;這時候最危險)ajax


如何防止CSRF攻擊

服務端端開啓 csrf認證以後,django

客戶端發送get請求 要form表單時,在裏面加上{% csrf_token %}一個隨機字符串json

客戶端收到這個 帶隨機字符串的 form表單以後後端

客戶端在向服務端 發post請求(不只要有cokie還檢查這個from表單是否是攜帶{% csrf_token %})
(不要覺得有了cokie就能夠隨意發送 post請求了!)瀏覽器


說白了就是:服務端生成隨機字符串發給客戶端,下次客戶端來了要檢查他的這個隨機字符串cookie

{% csrf_token %}{
<QueryDict: {'csrfmiddlewaretoken': ['Vk4rQ7L3d2stscFgHq7lKWTWSEcZrIRAAw3QJv6G2FLopBVJb7sONVbiP9aqDjgj'], 'user': ['我'], 'pwd': ['q'], 'gender': ['1'], 'login': ['yes']}>

 

Django應用CSRF

1.服務端所有禁用CSRF驗證

在項目的setings文件把這個 中間件註釋掉

'django.middleware.csrf.CsrfViewMiddleware',

 

二、局部使用

免除FBV的 CRFS驗證

from django.views.decorators.csrf import csrf_exempt
@csrf_exempt(免除)
def login(request):
    if request.method=='GET':
        return render(request,'login.html')
    else:
        print(request.POST)
        return HttpResponse('OK')

要求FBV使用CRFS驗證

from django.views.decorators.csrf import csrf_exempt,csrf_protect

@csrf_protect(保護)
def login(request):
    if request.method=='GET':
        return render(request,'login.html')
    else:
        print(request.POST)
        return HttpResponse('OK')

 

三、CBV應用CSRF驗證

要想在CBC局部使用或者禁用CRF驗證就必須 導入method_decorator(方法裝飾)

from django.utils.decorators import method_decorator
@method_decorator(csrf_exempt,name='dispatch')
class login(View):
    def get(self,request):
        return render(request,'login.html')

    def post(self,request):
        return HttpResponse("ok")

 

四、from表單添加CSRFtocken

 

 

{% csrf_token %}

 

 

 

 

 

Ajax應用CSRF

 

若是服務端開啓了CSRF驗證,客戶端就發送post請求就必須攜帶 服務端給的CSRF
那問題來了若是發 ajanx請求呢?

答案:客戶端發送 get請求時,服務端會把CSRF tocken放在form表單中(隱藏的input標籤)發送給客戶端

若是客戶端再發post請求給服務端找到這個標籤,name="csrfmiddlewaretoken"發送給服務端

<script src="/static/zhanggen.js"></script>
</head>
<body>
<h1>歡迎來到百合網</h1>
<form>
    
{#        服務端開啓csrf認證#}
    <p>用戶:<input type="text" name="user" ></p>
    <p>密碼:<input type="password" name="pwd"></p>
    <p>
        性別:男:<input type="radio" name="gender" value="1" b="1">
              女:<input type="radio" name="gender" value="2">
    </p>
    <p><input type="checkbox" name="login" value="yes" zhanggen="1">一週免登陸</p>
    <input type="button" value="提交" onclick="a()">
</form>
</body>
<script>
    function a(){
        tocken=$('[name="csrfmiddlewaretoken"]').val()
        $.ajax({
            url:'/login/',
            type:'POST',
            data:{'csrfmiddlewaretoken':tocken},
        或者這樣data:{'csrfmiddlewaretoken':'{{csrf_token}}'},最後福建小夥向淫王一問
        })
    }
</script>
</html>

 

二、若是沒有from表單攜帶CSRF的話,不要忘了CSRF的隨機字符串也會放在cookie裏面哦!!

從cookie中獲取csrftokenf須要藉助 jquery.cookie.js插件

/*!
 * jQuery Cookie Plugin v1.4.1
 * https://github.com/carhartl/jquery-cookie
 *
 * Copyright 2013 Klaus Hartl
 * Released under the MIT license
 */
(function (factory) {
    if (typeof define === 'function' && define.amd) {
        // AMD
        define(['jquery'], factory);
    } else if (typeof exports === 'object') {
        // CommonJS
        factory(require('jquery'));
    } else {
        // Browser globals
        factory(jQuery);
    }
}(function ($) {

    var pluses = /\+/g;

    function encode(s) {
        return config.raw ? s : encodeURIComponent(s);
    }

    function decode(s) {
        return config.raw ? s : decodeURIComponent(s);
    }

    function stringifyCookieValue(value) {
        return encode(config.json ? JSON.stringify(value) : String(value));
    }

    function parseCookieValue(s) {
        if (s.indexOf('"') === 0) {
            // This is a quoted cookie as according to RFC2068, unescape...
            s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\');
        }

        try {
            // Replace server-side written pluses with spaces.
            // If we can't decode the cookie, ignore it, it's unusable.
            // If we can't parse the cookie, ignore it, it's unusable.
            s = decodeURIComponent(s.replace(pluses, ' '));
            return config.json ? JSON.parse(s) : s;
        } catch(e) {}
    }

    function read(s, converter) {
        var value = config.raw ? s : parseCookieValue(s);
        return $.isFunction(converter) ? converter(value) : value;
    }

    var config = $.cookie = function (key, value, options) {

        // Write

        if (value !== undefined && !$.isFunction(value)) {
            options = $.extend({}, config.defaults, options);

            if (typeof options.expires === 'number') {
                var days = options.expires, t = options.expires = new Date();
                t.setTime(+t + days * 864e+5);
            }

            return (document.cookie = [
                encode(key), '=', stringifyCookieValue(value),
                options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
                options.path    ? '; path=' + options.path : '',
                options.domain  ? '; domain=' + options.domain : '',
                options.secure  ? '; secure' : ''
            ].join(''));
        }

        // Read

        var result = key ? undefined : {};

        // To prevent the for loop in the first place assign an empty array
        // in case there are no cookies at all. Also prevents odd result when
        // calling $.cookie().
        var cookies = document.cookie ? document.cookie.split('; ') : [];

        for (var i = 0, l = cookies.length; i < l; i++) {
            var parts = cookies[i].split('=');
            var name = decode(parts.shift());
            var cookie = parts.join('=');

            if (key && key === name) {
                // If second argument (value) is a function it's a converter...
                result = read(cookie, value);
                break;
            }

            // Prevent storing a cookie that we couldn't decode.
            if (!key && (cookie = read(cookie)) !== undefined) {
                result[name] = cookie;
            }
        }

        return result;
    };

    config.defaults = {};

    $.removeCookie = function (key, options) {
        if ($.cookie(key) === undefined) {
            return false;
        }

        // Must not alter options, thus extending a fresh object...
        $.cookie(key, '', $.extend({}, options, { expires: -1 }));
        return !$.cookie(key);
    };

}));
View Code

 

 


導入<script src="/static/jquery.cookie.js"></script>

發送ajax:data:{

"X-CSRFToken", $.cookie('csrftoken')

},

若是是在cookie裏面 獲取的 CSRF tocken(記號)就不能放在 ajax的請求體裏面了

放在請求頭裏,並且必須以這個格式(headers:{'X-CSRFToken':tocken},) 這是Django規定

注意cookie裏的 CSRF tocken和 from表單裏的不同

 

響應頭設置CSRF-Tocken,使用ajax向Django後臺發送json數據.

 $.ajax({
                type: 'POST',
                async: false,
                cache: false,
                url: '{% url "instance_add" %}',
                 headers:{"X-CSRFToken":$.cookie('csrftoken')},
                contentType: "application/json; charset=utf-8",
                dataType: "json",
                traditional:true,
                data:JSON.stringify({
                    "data_mode_type": $data_mode_type,
                    'database_type': $database_type,
                    'host': $host,
                    'port': $port,
                    'instance_nikename': $instance_nikename,
                    'db_business': $db_business,
                    'DBA': $DBA,
                    'responsible_person': $responsible_person
                }),
                success: function (data) {
                   alert(1)
                }
            });
        })
ajax
from django.shortcuts import render,HttpResponse,redirect
from DB_auto.form_validate.add_dbinfo import dbinfo_create
import json

def instance_add(request):
    if request.method=='POST':
        json_data=json.loads(request.body.decode('utf-8'))
        obj=dbinfo_create(json_data)
        if obj.is_valid():
            print(obj.cleaned_data)
        else:
            print(obj.errors)
    return render(request,'add_dbinfo.html')
django後臺使用form驗證json數據
相關文章
相關標籤/搜索