Cookie详解与跨域问题
Http是無狀態的協議,客戶端每次對服務端的http請求都是獨立的,不受該客戶端其它的請求的影響。
為了把Http這個無狀態協議變的與上下文有關系,我們引入了會話(Session)的概念,具有相同會話ID的請求使之變成了有狀態。
服務端可以給請求setSession的信息,信息保存在服務端內存,同時在response時將session內容推送給客戶端瀏覽器,瀏覽器為了保存SessionID等信息,又有了Cookie這玩意,Cookie本質是一塊存儲少量數據的存儲空間,可以存到內存也可以寫入磁盤。每次瀏覽器向一個域名發送http請求時會去查找該域名的Cookie信息拼接到Http的header中送到Server端。
?
談到域名,可以簡單的理解為我們訪問的地址(請注意不是真正映射成的IP地址),而Cookie具有不跨域性質,只會將屬于該域名的Cookie信息添加到Header中傳到Server端。
下面我們寫個Demo來試下Cookie的跨域
先設置下本機的host,添加兩個域名peer1和peer2。
用管理員權限打開C:\WINDOWS\system32\drivers\etc\hosts
添加兩行:
127.0.0.1?????? peer1
127.0.0.1?????? peer2
?
測試代碼放在了git上:https://github.com/yejingtao/forblog/tree/master/cookie-domain核心代碼如下:
@Value("${cookie.value}")String cookieValue;@RequestMapping("/setCookie")public String home(HttpServletResponse response,HttpServletRequest request) {Cookie cookie = new Cookie("testName", cookieValue);response.addCookie(cookie);return "Success";}@RequestMapping("/getCookie")public String home(HttpServletRequest request) {StringBuffer sb = new StringBuffer();Cookie[] cookies = request.getCookies();if(cookies!=null) {for(Cookie cookie : cookies) {sb.append(cookie.getName());sb.append(",");sb.append(cookie.getValue());sb.append(";");}}return sb.length()==0?"Empty":sb.toString();}測試前先看下我本機的cookie有哪些內容,需要對peer1和peer2這兩個域名做下清理:
以Chrome瀏覽器為例:
設置--高級—內容設置—cookie—查看所有cookie和網站數據,保證不要有peer1和peer2的cookie數據。
瀏覽器請求http://peer1:8087/setCookie,會發現cookie里多了peer1
打開箭頭可以看到詳細的cookie信息,cookie的屬性有我們代碼中顯式設置的,也有隱式默認的:
此時我們請求peer1的getCookie是可以獲取到cookie值的,請求peer2的getCookie是獲取不到cookie內容的,所以驗證了cookie是不能跨域的,而這個域是瀏覽器請求的域名,哪怕他們最終的服務端是一起的也不可以跨越。
上圖中cookie值里有個域名peer1,這個不是我們代碼中顯式設置的,瀏覽器默認幫我們根據域名設置的,那么如果我顯式設置一個跟域名對不上的domain會如何呢?
給setCookie代碼增加一行:
@RequestMapping("/setCookie")public String home(HttpServletResponse response,HttpServletRequest request) {Cookie cookie = new Cookie("testName", cookieValue);cookie.setDomain("peer2");response.addCookie(cookie); return "Success";}清理瀏覽器cookie、重啟服務后訪問peer1的setCookie
奇怪的是無論是peer1的getCookie還是peer2的getCookie都獲取不到cookie內容,而且設置里面也確實沒有。難道是瀏覽器自己的安全機制發現我set的Domain與域名不匹配所以認為這是個無效的cookie就沒有保存?調用下peer2的setCookie就可以驗證這一猜想,測試結果是肯定的。
Cookie是不安全的,瀏覽器、腳本類語言、甚至直接訪問cookie保存文本的地址都可以獲取到Cookie信息,所以盡量不要講敏感內容保存在cookie中,即便是密碼之類的可以進行加密,但是別人可以不需要解密直接使用你cookie中的內容進行欺騙。所以在服務端對cookie使用時,盡量設置超時時間,客戶端盡量cookie不使用時(例如瀏覽器關閉)及時清空。
?
Cookie是客戶端保存的內容,Session是服務端保存的內容,Session對于單個客戶來說是安全的,而Cookie是客戶共享的。所以可以推斷得出從安全角度講能用Session的情況盡量不要用Cookie,特別是現在Redis等共享緩存組件的使用使服務端存儲Session的能力大大加強。
最后回到本文最開始的那張圖,我們將代碼再修改下驗證下第一張圖。
代碼修改如下:
?
@RequestMapping("/setCookie")public String home(HttpServletResponse response,HttpServletRequest request) {request.getSession().setAttribute("sessionID", "haha");return "Success";}請求后瀏覽器會保留一個cookie來存取sessionID
總結
以上是生活随笔為你收集整理的Cookie详解与跨域问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 设置foxmail通过ccproxy代理
- 下一篇: 随机信号处理笔记 - ING