Cookie深度解析

Cookie深度解析

標籤: cookie
38571人閱讀 評論(17) 收藏 舉報
分類:

       本文來自:高爽|Coder,原文地址:http://blog.csdn.net/ghsau/article/details/20466351,轉載請註明。
       最近在公司作了Web端單點登陸(SSO)功能,基於Cookie實現,作完以後感受有必要總結一下,本文着重講解Cookie,下文會說明單點登陸的實現方案。css

Cookie簡介html

       衆所周知,Web協議(也就是HTTP)是一個無狀態的協議(HTTP1.0)。一個Web應用由不少個Web頁面組成,每一個頁面都有惟一的URL來定義。用戶在瀏覽器的地址欄輸入頁面的URL,瀏覽器就會向Web Server去發送請求。以下圖,瀏覽器向Web服務器發送了兩個請求,申請了兩個頁面。這兩個頁面的請求是分別使用了兩個單獨的HTTP鏈接。所謂無狀態的協議也就是表如今這裏,瀏覽器和Web服務器會在第一個請求完成之後關閉鏈接通道,在第二個請求的時候從新創建鏈接。Web服務器並不區分哪一個請求來自哪一個客戶端,對全部的請求都一視同仁,都是單獨的鏈接。這樣的方式大大區別於傳統的(Client/Server)C/S結構,在那樣的應用中,客戶端和服務器端會創建一個長時間的專用的鏈接通道。正是由於有了無狀態的特性,每一個鏈接資源可以很快被其餘客戶端所重用,一臺Web服務器纔可以同時服務於成千上萬的客戶端。
       可是咱們一般的應用是有狀態的。先不用提不一樣應用之間的SSO,在同一個應用中也須要保存用戶的登陸身份信息。例如用戶在訪問頁面1的時候進行了登陸,可是剛纔也提到,客戶端的每一個請求都是單獨的鏈接,當客戶再次訪問頁面2的時候,如何才能告訴Web服務器,客戶剛纔已經登陸過了呢?瀏覽器和服務器之間有約定:經過使用cookie技術來維護應用的狀態。Cookie是能夠被Web服務器設置的字符串,而且能夠保存在瀏覽器中。以下圖所示,當瀏覽器訪問了頁面1時,web服務器設置了一個cookie,並將這個cookie和頁面1一塊兒返回給瀏覽器,瀏覽器接到cookie以後,就會保存起來,在它訪問頁面2的時候會把這個cookie也帶上,Web服務器接到請求時也能讀出cookie的值,根據cookie值的內容就能夠判斷和恢復一些用戶的信息狀態。
java

Cookie組成web

       cookie是由名稱、內容、做用路徑、做用域、協議、生存週期組成,另外還有個HttpOnly屬性,HttpOnly屬性很重要,若是您在cookie中設置了HttpOnly屬性,那麼經過js腳本(document.cookie)將沒法讀取到cookie信息,這樣能必定程度上的防止XSS攻擊,關於XSS能夠看我以前的文章--XSS攻擊及防護。Tomcat服務器設置的JSESSIONID就是HttpOnly的。
       JavaEE中對cookie作了封裝,對應的是下面這個類:面試

java.lang.Object
  |
  +--javax.servlet.http.Cookie
       該類能夠設置cookie的名稱、內容、做用路徑、做用域、協議、生存週期,but不能設置HttpOnly屬性,不知道這麼作是出於什麼考慮,若是非要設置HttpOnly的cookie,咱們能夠經過響應頭來處理:
  1. response.setHeader("Set-Cookie""cookiename=value;Path=/;Domain=domainvalue;Max-Age=seconds;HttpOnly");  
Cookie做用域
       測試Cookie的做用域須要弄幾個域名,修改C:\Windows\System32\drivers\etc\hosts文件,將本機ip映射出四個域名,以下:
  1. 127.0.0.1 web1.ghsau.com  
  2. 127.0.0.1 web2.ghsau.com  
  3.   
  4. 127.0.0.1 web1.com  
  5. 127.0.0.1 web2.com  
       前兩個是2級域名(ghsau.com)相同,3級域名(web一、web2)不一樣,後兩個是2級域名不一樣。而後咱們再寫兩個jsp,一個用於設置Cookie,另外一個用於顯示Cookie。
       SetCookie.jsp:
  1. <%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>  
  2. <%  
  3.     Cookie cookie = new Cookie("test_key", "test_value");  
  4.     cookie.setPath("/");  
  5. //  cookie.setDomain(".ghsau.com");  
  6.     response.addCookie(cookie);  
  7. %>  
      ShowCookie.jsp:
  1. <%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>  
  2. <%  
  3.     // 輸出cookies,過濾掉JSESSIONID  
  4.     Cookie[] cookies = request.getCookies();  
  5.     if(cookies != null)  
  6.         for(Cookie cookie : cookies) {  
  7.             if(cookie.getName().equals("JSESSIONID"))    continue;  
  8.             out.println(cookie.getName() + "-" + cookie.getValue());  
  9.         }  
  10. %>  
       將這兩個jsp放到應用後,部署到服務器中,啓動服務器,咱們就能夠經過域名來訪問了。
       測試一,首先訪問http:// web1.ghsau.com:8080/WebSSOAuth/SetCookie.jsp,設置cookie後,再訪問http:// web1.ghsau.com:8080/WebSSOAuth/ShowCookie.jsp,頁面輸出test_key=test_value,這時咱們訪問http:// web2.ghsau.com:8080/WebSSOAuth/ShowCookie.jsp,發現頁面什麼都沒有輸出,這時咱們得出結論, cookie默認狀況下做用域爲當前域名
       測試二,將SetCookie.jsp第五行註釋打開,按照上面的順序依次訪問,咱們發現http:// web2.ghsau.com:8080/WebSSOAuth/ShowCookie.jsp中輸出了http:// web1.ghsau.com:8080/WebSSOAuth/SetCookie.jsp中設置的cookie,這時咱們得出結論, cookie做用域爲父級域名時,全部子級域名均可以獲得該cookie,這也是實現跨子域SSO的關鍵。這時有些朋友可能會想到那我把cookie做用域設置到頂級域名(.com、.net)上,是否是用該頂級域名的網站就都能獲取該cookie了?這樣設置的cookie,瀏覽器是不存儲的,無效的cookie。

       測試三,修改SetCookie.jsp第五行代碼爲cookie.setDomain(".web2.com"),首先訪問http://web1.com:8080/WebSSOAuth/SetCookie.jsp,設置cookie後,這時咱們訪問http://web2.com:8080/WebSSOAuth/ShowCookie.jsp,發現頁面什麼都沒有輸出,這時咱們得出結論,cookie不能跨二級域名設置api

Cookie安全性瀏覽器

       cookie中的數據一般會包含用戶的隱私數據,首先要保證數據的保密性,其次要保證數據不能被僞造或者篡改,基於這兩點,咱們一般須要對cookie內容進行加密,加密方式通常使用對稱加密(單密鑰,如DES)或非對稱加密(一對密鑰,如RSA),密鑰須要保存在服務器端一個安全的地方,這樣,別人不知道密鑰時,沒法對數據進行解密,也沒法僞造或篡改數據。另外,像上文提到的,重要的cookie數據須要設置成HttpOnly的,避免跨站腳本獲取你的cookie,保證了cookie在瀏覽器端的安全性。還有咱們能夠設置cookie只做用於安全的協議(https),JavaEE中能夠經過Cookie類的setSecure(boolean flag)來設置,設置後,該cookie只會在https下發送,而不會再http下發送,保證了cookie在服務器端的安全性,服務器https的設置能夠參照該文章
       本文來自:高爽|Coder,原文地址:http://blog.csdn.net/ghsau/article/details/20466351,轉載請註明。
安全

2
1
 
 

相關文章
相關標籤/搜索