雖然做web開發有一段時間了,但是對於同源策略和csrf安全策略理解一直不深刻,特抽出時間做了簡單的實驗進行理解。實驗過程如下,與大家一起分享。
實驗目的:驗證同源策略和csrf安全策略的關系和區別
實驗方案:1.Linux搭建django框架的python服務器(a);Windows搭建簡單的js服務器(b)
2.b的首頁中做了如下內容:(1)通過post\get方式提交向a表單
(2)通過ajax方式(post\get)向a請求數據
實驗結果:1.a沒有開啟csrf安全策略的情況下,打開b的首頁,b的頁面可以通過post\get方式正常的向a提交表單並得到回復頁面;但是通過ajax的get\post方式無法請求到a的數據。觀察a的log日志,發現b的request請求在a上能夠收到,但是b的request附帶的數據均加載不成功,b的ajax(get\post)請求均能得到a的response,在下發到打開b的瀏覽器時報出了同源策略的警告。
2.a開啟csrf安全策略的情況下,打開b的首頁,b的頁面可以通過get方式正常的向a提交表單並得到回復頁面,但是並不能通過post方式提交;b頁面通過ajax的get\post方式均無法請求到a的數據。
結論:1.同源策略:js語言的設計安全考慮,只允許同源訪問。非同源訪問也能向對應服務器發送請求,但是瀏覽器request中附帶的數據全部丟失,服務器能回傳request的response。但是在瀏覽器解析服務器下發的response階段會有同源策略的警告。(解釋基於js的ajax技術)
2.csrf安全策略:搭建服務器時的安全考慮,需要普通開發者進行相關的設計(框架一般自帶csrf安全策略的設計)。csrf策略過程為:在請求服務器的頁面時,服務器的response會向瀏覽器設置一個cookie,當有post方式的表單向服務器提交時,服務器設置的cookie會附加在瀏覽器的request中一起提交,服務器在接收request時,會驗證附加的cookie是否正確(每個用戶與服務器的通訊連接只有一個唯一的cookie,連接中斷后,下次連接時服務器會向瀏覽器設置新的cookie),只有cookie驗證通過才能下發正確的response,驗證失敗會有“403”錯誤碼下發。
1 # --------------Django服務器部分代碼--------------
2 # -*- coding:utf-8 -*-
3 from django.shortcuts import render 4 from django.http import HttpResponse, HttpResponseRedirect, JsonResponse 5
6 # Create your views here.
7
8
9 def index(request): 10
11 context = {'contents': 'hello world'} 12 # return HttpResponse("ok")
13 response= render(request, 'booktest/index.html', context) 14 return response 15
16
17 def args(request, id1, id2): 18
19 string = '%s--%s' % (id1, id2) 20 return HttpResponse(string) 21
22
23 def get1(request): 24
25 mode = request.encoding 26 dict = request.GET 27 a = dict.get('a') 28 b = dict.get('b') 29 c = dict.get('c') 30 string = 'method:%s--%s--%s--%s' % (mode, a, b, c) 31 return HttpResponse(string) 32
33
34 def get2(request): 35
36 dict = request.GET 37 a = dict.getlist('a') 38 b = dict.get('b') 39 c = dict.get('c') 40 d = dict.get('d', 'have no') 41 string = '%s--%s--%s--%s' % (a, b, c, d) 42 return HttpResponse(string) 43
44
45 def post(requst): 46
47 str_data = '---%s---%s' % (requst.method, requst.POST.get('uname')) 48
49 return HttpResponse(str_data) 50
51
52 def get3(request): 53
54 dict = request.GET 55 a = dict.get('a') 56 b = dict.get('b') 57 c = dict.get('c') 58 context = {'1': a, '2': b, '3': c} 59 # return HttpResponse("ok")
60 return HttpResponse(context) 61 # return render(request, 'booktest/get1.html', context)
62
63
64 def get4(request): 65
66 return HttpResponseRedirect('/admin/') 67
68
69 def ajax(request): 70
71 # return HttpResponse('ok')
72 return render(request, 'booktest/ajax.html/') 73
74
75 def json(request): 76
77 data1 = request.POST.get('csrfmiddlewaretoken') 78 data2 = request.POST.get('data') 79 print('------------%s------------%s---' % (data1, data2)) 80 a = {'h1': 'hello', 'h2': 'world', 'method': request.method, 'csrf': data1, 'data': data2} 81
82 return JsonResponse(a) 83
84
85 def cookie_set(request): 86 print('123') 87 cookie_value = 'hello'
88
89 response = HttpResponse("<h1>設置Cookie,請查看響應報文頭</h1>") 90 # response = HttpResponse("hello")
91 # Cookie中設置漢字鍵值對失敗
92 response.set_cookie('h1', cookie_value) 93 # return HttpResponse('ok')
94 return response 95
96
97 def cookie_get(request): 98
99 response = HttpResponse('<h1>讀取Cookie,數據如下:<br>') 100 cookies = request.COOKIES 101 if cookies.get('h1'): 102 response.write('<h1>'+cookies['h1']+'</h1>') 103
104 return response
1 <--Django服務器template部分的index.html代碼-->
2
3 <!DOCTYPE html>
4 <html lang="en">
5 <head>
6 <meta charset="utf-8">
7 <title>index</title>
8 </head>
9 <body>
10 {# <input type="button" value="返回">#} 11 <a href="/">返回主頁</a>
12
13 <hr>
14 <h1>參數</h1>
15 <a href="/get1/?a=1&b=2&c=3">get一鍵傳一值</a>
16 <br>
17 <a href="/get2/?a=1&b=2&c=3&a=5">get一鍵傳多值</a>
18 <br><br>
19 <form method="post" action="/post/">
20
21 {% csrf_token %} 22
23 姓名:<input type="text" name="uname"/><br>
24 密碼:<input type="password" name="upwd"/><br>
25 性別:<input type="radio" name="ugender" value="1"/>男 26 <input type="radio" name="ugender" value="0"/>女<br>
27 愛好:<input type="checkbox" name="uhobby" value="胸口碎大石"/>胸口碎大石 28 <input type="checkbox" name="uhobby" value="腳踩電燈炮"/>腳踩電燈炮 29 <input type="checkbox" name="uhobby" value="口吐火"/>口吐火<br>
30 <input type="submit" value="提交"/>
31 </form>
32
33 <hr>
34 <h1>GET屬性</h1>
35 <a href="/get3/?a=1&b=2&c=3">一鍵傳一值</a>
36 <br>
37 <a href="/get4/?a=1&b=2&c=3&a=5">一鍵傳多值</a>
38
39 <hr>
40 <h1>JsonResponse</h1>
41 <a href="/ajax/">ajax</a>
42
43 <hr>
44 <h1>Cookie</h1>
45 <a href="/cookie_set/">設置Cookie</a>
46 <br>
47 <a href="/get_Cookie/">獲取Cookie</a>
48 </body>
49 </html>
1 <--Django服務器ajax.html代碼-->
2
3 <!DOCTYPE html>
4 <html lang="en">
5 <head>
6 <meta charset="UTF-8">
7 <title>ajax</title>
8
9 <script src="/static/js/jquery-1.12.4.min.js"></script>
10 <script>
11 $(function () { 12 data1 = $('input[name="csrfmiddlewaretoken"]').prop('value'); 13 $('#btnjson').click(function () { 14 $.post('/json/', {'csrfmiddlewaretoken':data1,'data':'Hi Hellow'}, function (data) { 15 ul = $('#jsonlist'); 16 ul.append('<li>' + data['h1'] + '</li>'); 17 ul.append('<li>' + data['h2'] + '</li>'); 18 ul.append('<li>' + data['method'] + '</li>'); 19 ul.append('<li>' + data['csrf'] + '</li>'); 20 ul.append('<li>' + data['data'] + '</li>'); 21 }) 22 }); 23 }) 24 </script>
25 </head>
26 <body>
27 <div>hello world!</div>
28 {% csrf_token %} 29 <input type="button" id="btnjson" value="獲取json數據">
30 <ul id="jsonlist"></ul>
31 </body>
32 </html>
1 <--JS搭建的服務器首頁代碼-->
2
3 <!DOCTYPE html>
4 <html lang="en">
5 <head>
6 <meta charset="utf-8">
7 <title>index</title>
8
9
10 <script src="/js/jquery-1.12.4.min.js"></script>
11 <script>
12 $(function () { 13 data1 = $('input[name="csrfmiddlewaretoken"]').prop('value'); 14 $('#btnjson').click(function () { 15 $.get('http://192.168.27.128:8000/json/', {'csrfmiddlewaretoken':data1,'data':'HiHellow'}, function (data) { 16 ul = $('#jsonlist'); 17 ul.append('<li>' + data['h1'] + '</li>'); 18 ul.append('<li>' + data['h2'] + '</li>'); 19 ul.append('<li>' + data['method'] + '</li>'); 20 ul.append('<li>' + data['csrf'] + '</li>'); 21 ul.append('<li>' + data['data'] + '</li>'); 22 }) 23 }); 24 }) 25 </script>
26
27
28 </head>
29 <body>
30 {# <input type="button" value="返回">#} 31 <a href="/">返回主頁</a>
32
33 <hr>
34 <h1>參數</h1>
35 <a href="/get1/?a=1&b=2&c=3">get一鍵傳一值</a>
36 <br>
37 <a href="/get2/?a=1&b=2&c=3&a=5">get一鍵傳多值</a>
38 <br><br>
39 <form method="post" action="http://192.168.27.128:8000/post/">
40
41 {% csrf_token %} 42
43 姓名:<input type="text" name="uname"/><br>
44 密碼:<input type="password" name="upwd"/><br>
45 性別:<input type="radio" name="ugender" value="1"/>男 46 <input type="radio" name="ugender" value="0"/>女<br>
47 愛好:<input type="checkbox" name="uhobby" value="胸口碎大石"/>胸口碎大石 48 <input type="checkbox" name="uhobby" value="腳踩電燈炮"/>腳踩電燈炮 49 <input type="checkbox" name="uhobby" value="口吐火"/>口吐火<br>
50 <input type="submit" value="提交"/>
51 </form>
52
53 <hr>
54 <h1>GET屬性</h1>
55 <a href="/get3/?a=1&b=2&c=3">一鍵傳一值</a>
56 <br>
57 <a href="/get4/?a=1&b=2&c=3&a=5">一鍵傳多值</a>
58
59 <hr>
60 <h1>JsonResponse</h1>
61 <a href="/ajax/">ajax</a>
62
63 <hr>
64 <h1>Cookie</h1>
65 <a href="/cookie_set/">設置Cookie</a>
66 <br>
67 <a href="/get_Cookie/">獲取Cookie</a>
68
69 <hr>
70 <div>hello world!</div>
71 {% csrf_token %} 72 <input type="button" id="btnjson" value="獲取json數據">
73 <ul id="jsonlist"></ul>
74 </body>
75 </html>