前言:
夏洛:大爺狼钮,樓上322住的是馬冬梅家吧?
大爺:馬都什么捡絮?
夏洛:馬冬梅熬芜。
大爺:什么都沒啊福稳?
夏洛:馬冬梅啊涎拉。
大爺:馬什么沒?
夏洛:行,大爺你先涼快著吧鼓拧。
基于 http 協(xié)議的 web 應用程序是請求——應答模式是無狀態(tài)的半火,我們可以這樣理解:每次的請求都是獨立的,它的執(zhí)行情況和結(jié)果與前面的請求和之后的請求是無直接關(guān)系的季俩,它不會受前面的請求應答情況直接影響钮糖,也不會直接影響后面的請求應答情況。
為了讓Web服務器有記憶酌住,有狀態(tài)店归,有以下幾種方法。
Cookie
- 瀏覽器第一次訪問服務端時赂韵,服務器此時肯定不知道他的身份娱节,所以創(chuàng)建一個獨特的身份標識數(shù)據(jù),格式為key=value祭示,放入到Set-Cookie字段里肄满,隨著響應報文發(fā)給瀏覽器。
- 瀏覽器看到有Set-Cookie字段以后就知道這是服務器給的身份標識质涛,于是就保存起來稠歉,下次請求時會自動將此key=value值放入到Cookie字段中發(fā)給服務端。
- 服務端收到請求報文后汇陆,發(fā)現(xiàn)Cookie字段中有值怒炸,就能根據(jù)此值識別用戶的身份然后提供個性化的服務。
Cookie
就是服務器委托瀏覽器存儲在客戶端里的一些數(shù)據(jù)毡代,而這些數(shù)據(jù)通常都會記錄用戶的關(guān)鍵識別信息阅羹。所以Cookie
需要用一些其他的手段用來保護,防止外泄或者竊取教寂,這些手段就是Cookie
的屬性捏鱼。
參數(shù)名 | 作用 | 后端設置方法 |
---|---|---|
Max-Age | 設置cookie的過期時間,單位為秒 | cookie.setMaxAge(10) |
Domain | 指定了Cookie所屬的域名 | cookie.setDomain("") |
Path | 指定了Cookie所屬的路徑 | cookie.setPath(""); |
HttpOnly | 告訴瀏覽器此Cookie只能靠瀏覽器Http協(xié)議傳輸,禁止其他方式訪問 | cookie.setHttpOnly(true) |
Secure | 告訴瀏覽器此Cookie只能在Https安全協(xié)議中傳輸,如果是Http則禁止傳輸 | cookie.setSecure(true) |
Path
設置為cookie.setPath("/testCookies")酪耕,接下來我們訪問http://localhost:8005/testCookies导梆,我們可以看到在左邊和我們指定的路徑是一樣的,所以Cookie才在請求頭中出現(xiàn)迂烁,接下來我們訪問http://localhost:8005看尼,我們發(fā)現(xiàn)沒有Cookie字段了,這就是Path控制的路徑盟步。
Domain
設置為cookie.setDomain("localhost")藏斩,接下來我們訪問http://localhost:8005/testCookies我們發(fā)現(xiàn)下圖中左邊的是有Cookie的字段的,但是我們訪問http://172.16.42.81:8005/testCookies却盘,看下圖的右邊可以看到?jīng)]有Cookie的字段了狰域。這就是Domain控制的域名發(fā)送Cookie窜觉。
Session
Cookie是存儲在客戶端方,Session是存儲在服務端方北专,客戶端只存儲SessionId
@RequestMapping("/testSession")
@ResponseBody
public String testSession(HttpSession session){
session.setAttribute("testSession","this is my session");
return "testSession";
}
@RequestMapping("/testGetSession")
@ResponseBody
public String testGetSession(HttpSession session){
Object testSession = session.getAttribute("testSession");
return String.valueOf(testSession);
}
我們在請求參數(shù)中加上HttpSession session,然后再瀏覽器中輸入http://localhost:8005/testSession進行訪問可以看到在服務器的返回頭中在Cookie中生成了一個SessionId旬陡。然后瀏覽器記住此SessionId下次訪問時可以帶著此Id拓颓,然后就能根據(jù)此Id找到存儲在服務端的信息了。
過期時間:
客戶端:和Cookie過期一致描孟,如果沒設置驶睦,默認是關(guān)了瀏覽器就沒了,即再打開瀏覽器的時候初次請求頭中是沒有SessionId了匿醒。
服務端:服務端的過期是真的過期场航,即服務器端的Session存儲的數(shù)據(jù)結(jié)構(gòu)多久不可用了,默認是30分鐘廉羔。
Session是存儲在Tomcat(以此為例)的容器中溉痢,所以如果后端機器是多臺的話,因此多個機器間是無法共享Session的憋他,此時可以使用Spring提供的分布式Session的解決方案孩饼,是將Session放在了Redis中。
Token
Session是將要驗證的信息存儲在服務端竹挡,并以SessionId和數(shù)據(jù)進行對應镀娶,SessionId由客戶端存儲,在請求時將SessionId也帶過去揪罕,因此實現(xiàn)了狀態(tài)的對應梯码。而Token是在服務端將用戶信息經(jīng)過Base64Url編碼過后傳給在客戶端,每次用戶請求的時候都會帶上這一段信息好啰,因此服務端拿到此信息進行解密后就知道此用戶是誰了轩娶,這個方法叫做JWT(Json Web Token)。
Token相比較于Session的優(yōu)點在于坎怪,當后端系統(tǒng)有多臺時罢坝,由于是客戶端訪問時直接帶著數(shù)據(jù),因此無需做共享數(shù)據(jù)的操作搅窿。
Token的優(yōu)點
- 簡潔:可以通過URL,POST參數(shù)或者是在HTTP頭參數(shù)發(fā)送嘁酿,因為數(shù)據(jù)量小,傳輸速度也很快
- 自包含:由于串包含了用戶所需要的信息男应,避免了多次查詢數(shù)據(jù)庫
- 因為Token是以Json的形式保存在客戶端的闹司,所以JWT是跨語言的
- 不需要在服務端保存會話信息,特別適用于分布式微服務
CSRF攻擊
可以這么理解:有一個人發(fā)給你一個搞(mei)笑(nv)圖片鏈接沐飘,你打開這個鏈接之后游桩,便立刻收到了短信:你的銀行里的錢已經(jīng)轉(zhuǎn)移到這個人的帳戶了赋焕。
1.登錄受信任網(wǎng)站A,并在本地生成Cookie充岛。
2.在不登出A的情況下敦姻,訪問危險網(wǎng)站B。
CSRF 攻擊的對象
在討論如何抵御 CSRF 之前铐刘,先要明確 CSRF 攻擊的對象陪每,也就是要保護的對象。從以上的例子可知镰吵,CSRF 攻擊是黑客借助受害者的 cookie 騙取服務器的信任檩禾,但是黑客并不能拿到 cookie,也看不到 cookie 的內(nèi)容疤祭。另外盼产,對于服務器返回的結(jié)果,由于瀏覽器同源策略的限制勺馆,黑客也無法進行解析戏售。因此,黑客無法從返回的結(jié)果中得到任何東西草穆,他所能做的就是給服務器發(fā)送請求蜈项,以執(zhí)行請求中所描述的命令,在服務器端直接改變數(shù)據(jù)的值续挟,而非竊取服務器中的數(shù)據(jù)紧卒。所以,我們要保護的對象是那些可以直接產(chǎn)生數(shù)據(jù)改變的服務诗祸,而對于讀取數(shù)據(jù)的服務跑芳,則不需要進行 CSRF 的保護。比如銀行系統(tǒng)中轉(zhuǎn)賬的請求會直接改變賬戶的金額直颅,會遭到 CSRF 攻擊博个,需要保護。而查詢余額是對金額的讀取操作功偿,不會改變數(shù)據(jù)盆佣,CSRF 攻擊無法解析服務器返回的結(jié)果,無需保護械荷。
當前防御 CSRF 的幾種策略
- 驗證 HTTP Referer 字段
服務器驗證Referer 字段共耍,如果不是受信網(wǎng)站則拒絕請求。
問題:使用驗證 Referer 值的方法吨瞎,就是把安全性都依賴于第三方(即瀏覽器)來保障痹兜,從理論上來講,這樣并不安全颤诀。事實上字旭,對于某些瀏覽器对湃,比如 IE6 或 FF2,目前已經(jīng)有一些方法可以篡改 Referer 值遗淳。如果 bank.example 網(wǎng)站支持 IE6 瀏覽器拍柒,黑客完全可以把用戶瀏覽器的 Referer 值設為以 bank.example 域名開頭的地址,這樣就可以通過驗證屈暗,從而進行 CSRF 攻擊斤儿。并且用戶可以設置不使用Referer。非100%安全恐锦。
用戶操作限制,比如驗證碼
嚴重影響了用戶體驗疆液,而且還有額外的開發(fā)成本Token驗證的CSRF防御機制是公認最合適的方案
參考文檔
- cookie session token
https://segmentfault.com/a/1190000021185229 - CSRF攻擊和跨域
https://segmentfault.com/a/1190000021029334
https://segmentfault.com/a/1190000005125790
https://segmentfault.com/a/1190000006944760
https://segmentfault.com/a/1190000003716037
https://www.ibm.com/developerworks/cn/web/1102_niugang_csrf/
3.web安全周刊
https://segmentfault.com/a/1190000007564080