該協議主要是闡述如何利用HTTP Cookie與SetCookie頭欄位來實現對HTTP Request
狀態的跟蹤與管理,這個在使用者行為分析,登入系統設計等方法有著很重要的應用。對
於大多數現代的瀏覽器都支援RFC6265.
基本原理:
RFC6265闡述通過設定SetCookie不同值在HTTPResponse中,來告訴瀏覽器用戶端在
接下來的每次請求Request Header中都帶上Response中指定的值與行為。直到伺服器
配置的session到期為止。通過Tomcat配置session到期時間為30分鐘,在web.xml配置
檔案中可以重寫該屬性值。同時當使用者關閉瀏覽器以後,在用戶端記憶體中對於該網站
的cookie內容將會自動銷毀。也許這樣不太方便使用者,於是很多網站提供了記住自己帳
號的原因,其實就是通過將cookie寫到本地檔案中。
系統訪問與重新導向到登入頁面
首先當瀏覽器用戶端發起一個Request請求訪問指定URL或者Web Server時,伺服器
端通過檢查要求標頭是否含有Cookie欄位,以及Cookie欄位中的內容來設別訪問者是否
為登入或者未登入使用者,如果是未登入頁面,則將URL重新導向到登入頁面即可。使用者
登入以後伺服器端發送一個HTTP Response + Set-Cookie內容到用戶端瀏覽器,那麼
在隨後所有發往該Domain的URL都將會帶上Set-Cookie中指定的內容,HTTP
Request + Cookie到伺服器端,伺服器端通過檢查Request 頭中Cookie內容實現對
使用者的狀態追蹤。從而將無狀態HTTP Request變成一個有狀態的HTTP串連加以
管理。登入處理基本的流程圖如下:
伺服器與用戶端HTTP Request發送與接受狀態:
使用者退出系統與Request狀態終止
當用戶端關閉瀏覽器時候,用戶端Cookie將會被自動從記憶體中丟棄,當用戶端再次打
開瀏覽器請求伺服器端資源時候,將被要求再次登入到伺服器端建立新的可跟蹤的
Request 會話當超過伺服器端配置的會話時間時,同樣會要求使用者再次登入系統。
當使用者使用系統退出功能正常退出時,當退出時候通過設定Max-Age : 0來remove
當前cookie內容實現對用戶端狀態的清零。只要在HTTP Response中加上Cookie過
期屬性同時設定一個過去的時間。例子如下:
RFC6265中關於Cookie與SetCookie的屬性與使用詳解
Cookie |
SetCookie |
包含於HTTP Request Header,使用者用戶端向伺服器端發送驗證資訊與其它有用資訊,主要用來跟蹤用戶端狀態與分析使用者行為 |
在HTTP Response中設定,主要用於伺服器端向用戶端發送指定的狀態資訊,建立與用戶端的聯絡。通過設定HTTPOnly屬性與Secure屬性還可以保護用戶端Cookie資料,減少惡意讀取使用者Cookie資訊發生。 |
RFC6265中一個簡單例子:
== Server -> UserAgent == // 伺服器發送到用戶端
Set-Cookie:SID=31d4d96e407aad42
== User Agent ->Server == // 每個請求中都會帶上SID資訊,實現追蹤使用者狀態
Cookie: SID=31d4d96e407aad42
要求用戶端的所有請求路徑都要帶上SID資訊,通過發送Path=/實現
== Server -> UserAgent ==
Set-Cookie:SID=31d4d96e407aad42; Path=/; Domain=example.com
== User Agent ->Server ==
Cookie: SID=31d4d96e407aad42
刪除用戶端Request Cookie中SID資訊,取目前時間以前的一個任意時間。
== Server -> UserAgent ==
Set-Cookie: SID=;Expires=Sun, 06 Nov 1994 08:49:37 GMT
最後來看一看我抓取的CSDN登入以後的Cookie資訊:
J2EE 當從HTTP Servlet Request中調用擷取SessionID方法以後會自動把JSESSIONID
作為Cookie設定到Response頭中。所以無需顯式再次調用!
根據RFC6265的內容,基於Spring3 MVC我自己也實現了一個簡單的登入系統設計
可以協助大家更好的理解協議。只有兩個頁面,兩個Controller類與一個ServletFilter
各個類的作用大致如下:
ServletFilter類:實現對HTTP Request頭的檢查,跟蹤使用者狀態
兩個Controller類:一個用來系統管理使用者登入登出,一個是簡單的擷取首頁面資訊
其中ServletFilter類代碼如下:
package com.edinme.exam.filter;import java.io.IOException;import java.util.Date;import javax.servlet.Filter;import javax.servlet.FilterChain;import javax.servlet.FilterConfig;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import com.editme.exam.util.FilterUtil;public class SingleSignOnFilter implements Filter{ @Overridepublic void destroy() {// TODO Auto-generated method stub}@Overridepublic void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException {HttpServletRequest httpRequest = (HttpServletRequest) request;HttpServletResponse httpResponse = (HttpServletResponse) response;String ipAddress = httpRequest.getRemoteAddr();// get URI resource pathString uriPath = httpRequest.getRequestURI();String contextPath = httpRequest.getContextPath();String cookie = httpRequest.getHeader("Cookie");String sessionId = httpRequest.getSession().getId(); // enable SetCookie header in HTTP Responseif(FilterUtil.validURLRequest(uriPath, cookie, contextPath, sessionId)){System.out.println("Request URI : " + uriPath);System.out.println("IP "+ipAddress + ", Time " + new Date().toString());chain.doFilter(request, response);}else{System.out.println(httpRequest.getProtocol() + httpRequest.getLocalPort() + httpRequest.getContextPath());httpResponse.sendRedirect("/exam/user.do");}}@Overridepublic void init(FilterConfig config) throws ServletException {// TODO Auto-generated method stub}}使用者登入登出Controller:
package com.edinme.exam.controller;import javax.servlet.http.Cookie;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.ResponseBody;import org.springframework.web.servlet.ModelAndView;import com.edinme.exam.dto.MockUpDataFactory;import com.edinme.exam.dto.UserDto;import com.editme.exam.util.FilterUtil;@Controller@RequestMapping(value = "/user")public class UserLoginController {@RequestMapping(method = RequestMethod.GET)public ModelAndView goLoginPage(){System.out.println("Dispaly SSO Page");ModelAndView view = new ModelAndView("user");return view;}@RequestMapping(value = "signIn", method = RequestMethod.GET)@ResponseBodypublic UserDto login(@RequestParam String userId, @RequestParam String password, /*HttpServletRequest httpRequest,*/ HttpServletResponse response){System.out.println("User Name = " + userId);MockUpDataFactory dataFactory = new MockUpDataFactory();response.addHeader("Set-Cookie", "userId=" + userId + "; Path=" + FilterUtil.CONTEXT_PATH + "; HttpOnly");return dataFactory.getUserById(userId);}@RequestMapping(value = "signOut", method = RequestMethod.GET)@ResponseBodypublic UserDto logout(@RequestParam String userId, HttpServletRequest httpRequest, HttpServletResponse response){MockUpDataFactory dataFactory = new MockUpDataFactory();//Set-Cookie:JSESSIONID=delete; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Path=/exam///Set-Cookie:userId=delete; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Path=/exam/Cookie[] cs = httpRequest.getCookies();for(Cookie c : cs){c.setMaxAge(0); // set expire attributec.setValue("delete");c.setPath(FilterUtil.CONTEXT_PATH); // set path, must be same as login context pathresponse.addCookie(c);}response.setHeader("Expires", "Thu, 19 Nov 1981 08:52:00 GMT"); // must be GTM formatreturn dataFactory.getUserById(userId);}////public static void main(String[] args)//{//SimpleDateFormat sdf = new SimpleDateFormat("E dd MMM yyyy HH:mm:ss zzz", Locale.ENGLISH);//sdf.setTimeZone(TimeZone.getTimeZone("GMT"));//System.out.println(sdf.format(new Date()));//}}
全部原始碼下載點擊這裡:
http://download.csdn.net/detail/jia20003/7087947
覺得好請頂一下啊!!,謝謝!!