Session与Cookie的安全问题
由于http協議是無狀態的協議,為了能夠記住請求的狀態,于是引入了Session和Cookie的機制。我們應該有一個很明確的概念,那就是Session是存在于服務器端的,在單體式應用中,他是由tomcat管理的,存在于tomcat的內存中,當我們為了解決分布式場景中的session共享問題時,引入了redis,其共享內存,以及支持key自動過期的特性,非常契合session的特性,我們在企業開發中最常用的也就是這種模式。但是只要你愿意,也可以選擇存儲在JDBC,Mongo中,這些,spring都提供了默認的實現,在大多數情況下,我們只需要引入配置即可。而Cookie則是存在于客戶端,更方便理解的說法,可以說存在于瀏覽器。Cookie并不常用,至少在我不長的web開發生涯中,并沒有什么場景需要我過多的關注Cookie。http協議允許從服務器返回Response時攜帶一些Cookie,并且同一個域下對Cookie的數量有所限制,之前說過Session的持久化依賴于服務端的策略,而Cookie的持久化則是依賴于本地文件。雖然說Cookie并不常用,但是有一類特殊的Cookie卻是我們需要額外關注的,那便是與Session相關的sessionId【也放在cookie中】,他是真正維系客戶端和服務端的橋梁。
一、代碼示例
用戶發起請求,服務器響應請求,并做一些用戶信息的處理,隨后返回響應給用戶;用戶再次發起請求,攜帶sessionId,服務器便能夠識別,這個用戶就是之前請求的那個。使用Springboot編寫一個非常簡單的服務端,來加深對其的理解。需求很簡單,當瀏覽器訪問localhost:8080/test/cookie?browser=xxx時,如果沒有獲取到session,則將request中的browser存入session;如果獲取到session,便將session中的browser值輸出。順便將request中的所有cookie打印出來。
@Controller public class CookieController {@RequestMapping("/test/cookie")public String cookie(@RequestParam("browser") String browser, HttpServletRequest request, HttpSession session) {//取出session中的browserObject sessionBrowser = session.getAttribute("browser");if (sessionBrowser == null) {System.out.println("不存在session,設置browser=" + browser);session.setAttribute("browser", browser);} else {System.out.println("存在session,browser=" + sessionBrowser.toString());}Cookie[] cookies = request.getCookies();if (cookies != null && cookies.length > 0) {for (Cookie cookie : cookies) {System.out.println(cookie.getName() + " : " + cookie.getValue());}}return "index";} }我們沒有引入其他任何依賴,看看原生的session機制是什么。
既沒有session,也沒有cookie,我們將browser=chrome設置到session中。
再次訪問同樣的端點,控制臺輸出如下:
Session Info: 存在session,browser=chrome Cookie Info: JSESSIONID : 4CD1D96E04FC390EA6C60E8C40A636AF多次訪問之后,控制臺依舊打印出同樣的信息。
稍微解讀下這個現象,可以驗證一些結論。當服務端往session中保存一些數據時,Response中自動添加了一個Cookie:JSESSIONID:xxxx,再后續的請求中,瀏覽器也是自動的帶上了這個Cookie,服務端根據Cookie中的JSESSIONID取到了對應的session。這驗證了一開始的說法,客戶端服務端是通過JSESSIONID進行交互的,并且,添加和攜帶key為JSESSIONID的Cookie都是tomcat和瀏覽器自動幫助我們完成的,這很關鍵。
第一次訪問:
Session Info: 不存在session,設置browser=360后續訪問:
Session Info: 存在session,browser=360 Cookie Info: JSESSIONID : 320C21A645A160C4843D076204DA2F40為什么要再次使用另一個瀏覽器訪問呢?先賣個關子,我們最起碼可以得出結論,不同瀏覽器,訪問是隔離的,甚至重新打開同一個瀏覽器,JSESSIONID也是不同的。另外可以嘗試把保存session的操作注視掉,則可以發現Response中就不會返回JSESSIONID了,即這是一次無狀態的請求。
二、安全問題
其實上述的知識點,都是非常淺顯的,之所以啰嗦一句,是為了引出這一節的內容,以及方便觀察后續我們引入Spring Session之后的發生的變化。
還記得上一節的代碼示例中,我們使用了兩個瀏覽器:
- chrome瀏覽器訪問時,JSESSIONID為4CD1D96E04FC390EA6C60E8C40A636AF,后端session記錄的值為:browser=chrome。
- 360瀏覽器訪問時,JSESSIONID為320C21A645A160C4843D076204DA2F40,后端session記錄的值為:browser=360。
我們使用chrome插件Edit this Cookie,將chrome瀏覽器中的JSESSIONID修改為360瀏覽器中的值
同樣訪問原來的端點:localhost:8080/test/cookie?browser=chrome,得到的輸出如下:
存在session,browser=360 JSESSIONID : 320C21A645A160C4843D076204DA2F40證實了一點,存放在客戶端的Cookie的確是存在安全問題的,我們使用360的JSESSIONID“騙”過了服務器。畢竟,服務器只能通過Cookie中的JSESSIONID來辨別身份。(這提示我們不要在公共場合保存Cookie信息,現在的瀏覽器在保存Cookie時通常會讓你確定一次)
參考文章
總結
以上是生活随笔為你收集整理的Session与Cookie的安全问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 见实私域流量运营词汇手册(1.0版)
- 下一篇: 网络游戏知识产权保护白皮书