一、cookie介紹
1.cookie的本來面目
HTTP協議本身是無狀態的。什么是無狀態呢,即服務器無法判斷用戶身份。Cookie實際上是一小段的文本信息(key-value格式)。客戶端向服務器發起請求,如果服務器需要記錄該用戶狀態,就使用response向客戶端瀏覽器頒發一個Cookie。客戶端瀏覽器會把Cookie保存起來。當瀏覽器再請求該網站時,瀏覽器把請求的網址連同該Cookie一同提交給服務器。服務器檢查該Cookie,以此來辨認用戶狀態。
2.cookie本來運行機制
當用戶第一次訪問並登陸一個網站的時候,cookie的設置以及發送會經歷以下4個步驟:
客戶端發送一個請求到服務器 --》 服務器發送一個HttpResponse響應到客戶端,其中包含Set-Cookie的頭部 --》 客戶端保存cookie,之后向服務器發送請求時,HttpRequest請求中會包含一個Cookie的頭部 --》服務器返回響應數據。
3.cookie的屬性及值
name-cookie的名稱(name區分大小寫)
value-存儲在cookie中的字符串值,當值為中文時,必須進行url編碼。
Max-Age/Expires-cookie的有效期(默認值:-1)
該屬性用來設置Cookie的有效期。Cookie中的maxAge用來表示該屬性,單位為秒。
在js中,通過expires來設置cookie的到期時間;
在java中,通過getMaxAge()和setMaxAge(int maxAge)來讀寫Max-Age屬性。
maxAge有3種值,分別為正數,負數和0。
如果maxAge屬性為正數,則表示該Cookie會在maxAge秒之后自動失效。瀏覽器會將maxAge為正數的Cookie持久化,即寫到對應的Cookie文件中(每個瀏覽器存儲的位置不一致)。無論客戶關閉了瀏覽器還是電腦,只要還在maxAge秒之前,登錄網站時該Cookie仍然有效。
當maxAge屬性為負數,則表示該Cookie只是一個臨時Cookie,不會被持久化,僅在本瀏覽器窗口或者本窗口打開的子窗口中有效,關閉瀏覽器后該Cookie立即失效。
當maxAge為0時,表示立即刪除Cookie。
Domain-cookie的域名(默認值:當前網址的域名)
Cookie是不可以跨域名的,隱私安全機制禁止網站非法獲取其他網站的Cookie。
正常情況下,同一個一級域名下的兩個二級域名也不能交互使用Cookie,比如test1.mcrwayfun.com和test2.mcrwayfun.com,因為二者的域名不完全相同。如果想要mcrwayfun.com名下的二級域名都可以使用該Cookie,需要設置Cookie的domain參數為.mcrwayfun.com,這樣使用test1.mcrwayfun.com和test2.mcrwayfun.com就能訪問同一個cookie。
一級域名又稱為頂級域名,一般由字符串+后綴組成。熟悉的一級域名有baidu.com,qq.com。com,cn,net等均是常見的后綴。
二級域名是在一級域名下衍生的,比如有個一級域名為mcrfun.com,則blog.mcrfun.com和www.mcrfun.com均是其衍生出來的二級域名。
path-表示這個cookie影響到的路徑,瀏覽器跟會根據這項配置,向指定域中匹配的路徑發送cookie。(默認值:只在當前請求路徑及子路徑下有效)
HttpOnly-告知瀏覽器不允許通過腳本document.cookie去更改這個值,也不能通過document.cookie獲取該cookie。(默認值:false),可通過服務端設置,前端無法設置。
但在http請求張仍然會攜帶這個cookie。注意這個值雖然在腳本中不可獲取,但仍然在瀏覽器安裝目錄中以文件形式存在。這項設置通常在服務器端設置。也可以通過瀏覽器的開發者工具查看到。
secure-安全標志,指定后,只有在使用SSL鏈接時候才能發送到服務器,如果是http鏈接則不會傳遞該信息。就算設置了secure 屬性也並不代表他人不能看到你機器本地保存的 cookie 信息,所以不要把重要信息放cookie就對了服務器端設置。(默認值:false)
二、js 獲取、添加、修改、刪除cookie
准備工作:打開瀏覽器,隨便訪問一個網頁,f12打開網頁調試工具。
1.獲取cookie
獲取全部cookie
var cookies = document.cookie;
舉例:在控制台輸入document.cookie-->回車-->輸出的是該網站所有的cookie信息。
獲取指定的cookie(優化前)
var cookieName = "cookie名稱"; var cookieValue = document.cookie.match(new RegExp("(^| )" + cookieName + "=([^;]*)(;|$)"))[2];
舉例:獲取cookie _ga的值。
獲取指定的cookie(優化后)
var cookieName = "cookie名稱"; var cookieValue = ""; try { cookieValue = document.cookie.match(new RegExp("(^| )" + cookieName + "=([^;]*)(;|$)"))[2]; } catch(e) {//捕獲異常的目的是為了讓下面的代碼繼續執行;因為當要查找的cookie不存在時,上一行代碼會報錯。 cookieValue = null; };
2.添加cookie
2.1格式:
document.cookie = "cookie名稱=cookie值;expires=過期時間;path=/可以訪問到該cookie的路徑;domain=網站域名;secure=true/false;";
2.2只添加cookie,不設置屬性。
舉例:在控制台輸入document.cookie = "username=Marydon;";-->回車
2.3添加cookie, 設置可訪問路徑
舉例:在本頁面添加cookie
第一步:查看當前頁面的訪問路徑
http://localhost:8080/zz/weixin/about.do,訪問路徑為:/zz/weixin/about.do,要想在該cookie只在當前頁面生效,就需要將path設置為該頁面的完整訪問路徑。
第二步:在控制台輸入document.cookie = "username=Marydon;path=/zz/weixin/about.do";-->回車;
第三步:刷新當前頁面cookie-->cookie已經添加成功-->cookie的路徑已經設置好。
2.4探究一:添加cookie,不設置path屬性與添加cookie,設置path屬性的區別
先看看添加cookie,不設置path屬性de默認path的值
添加成功后,你會發現:當不設置path屬性時,cookie的默認路徑為該頁面請求路徑的上級目錄,即:/zz/weixin,
表示的是:所有頁面路徑在/zz/weixin/*下都可獲取到該cookie值。
小結:
也就是說:未設置path屬性時,並不是只有當前頁面可以訪問得到,和它同級的訪問路徑(/zz/weixin/about2.do)都可以訪問得到。
添加cookie,設置path屬性時,path的路徑可以隨意設置,既可以設置僅僅本頁面有效,也可以設置其它頁面有效。
2.5探究二:添加cookie,必須設置path屬性的情景
在A頁面添加cookie,供B頁面使用,而A、B兩個頁面又不是同級目錄(不是磁盤目錄而是通過瀏覽器訪問該頁面時的請求路徑)時,必須將path屬性設置為B頁面的訪問路徑。
兩個頁面雖然同在同一目錄,但是通過瀏覽器並不是直接訪問該頁面,而是通過服務器轉發到對應頁面。
about.jsp的訪問路徑為:http://localhost:8080/zz/weixin/about.do
about2.jsp的訪問路徑為:http://localhost:8080/zz/weixin2/about.do
訪問A頁面,添加cookie,不設置path屬性;
此時,username的可訪問路徑為/zz/weixin,只有/zz/weixin/*路徑下可訪問到該cookie。
訪問B頁面,未找到cookie:username。
在A頁面控制台添加path,設置為:/zz/weixin2/about.do
添加成功,刷新A頁面的cookie,該cookie並未添加到該頁面,說明邏輯沒有錯誤,這才是合理情況。
再次來到B頁面,刷新cookie,username添加成功。
這就是解決兩個完全不同訪問路徑下,能夠實現cookie傳遞的本質。
2.6探究三:添加cookie,不設置path屬性
此時,和它同級的訪問路徑(/zz/weixin/about2.do)都可以訪問得到,下面來證實一下。
沒有添加path屬性
按照道理來講,/zz/weixin/aa.do該頁面是可以訪問得到該cookie的。
沒有問題,結論正確。
2.7添加cookie, 設置有效期。
舉例:1分鍾之后過期。
// 1分鍾之內有效 var oDate = new Date(); oDate.setMilliseconds(oDate.getMilliseconds() + 1*60*1000); var time = oDate.toUTCString(); /*添加cookie,設置有效期*/document.cookie = "username=Marydon;expires=" + time + ";";
添加成功后,刷新cookie,設置成功。
一分鍾后,再次刷新cookie。
username的cookie已經消失。
3.修改、刪除cookie
3.1修改cookie;
和添加cookie的方法一致,直接賦值即可。
格式:document.cookie = "cookie名稱=cookie值;expires=過期時間;path=/可以訪問到該cookie的路徑;domain=網站域名;secure=true/false;";
舉例1:沒有設置path和domain(path和domain都采用默認值)
修改前
修改后,document.cookie="username=Mary"
舉例2: 設置path(path沒有采用默認值)
修改前,path=/zz/index.jsp
修改后,document.cookie="username=Marydon;path=/zz/index.jsp"
注意:
第一點,cookie區分大小寫,如果大小寫不一致就變成了添加而不是修改;
第二點,如果設置了path或domain,則也需要保持一致,否則,也會變成添加而不是修改。
3.2刪除cookie。
cookie沒有提供刪除的方法,但是我們可以曲線救國。
方法一:將cookie的值清空。
正確方式:
documen.cookie="username=";//默認path和domain
錯誤方式一: document.cookie="username=null";
錯誤方式二:document.cookie="username=''";
cookie的值只有一種表現形式:字符串。這兩種方式都是犯了同樣的錯誤,不管你設置成什么,表現形式都只是字符串。
按照正確方式清空cookie后,該cookie的返回值為""。
方法二:設置cookie過期。
讓cookie立馬過期,本質就是立馬刪除這個cookie。只需要將指定cookie的過期時間設置為當前時間之前即可。
var cookieName = "username"; // 將指定cookie的過期時間設置為當前時間之前 var expires=new Date(); expires.setTime(expires.getTime()-1); document.cookie= cookieName + "=;expires=" + expires.toGMTString();
將以上代碼拷貝到控制台,運行,刪除成功。
三、java 獲取、添加、修改、刪除cookie
導包:
import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;
1.獲取cookie
方式一:獲取cookie對象
/** * 獲取cookie對象 * @param cookieName cookie名稱 * @return cookie對象 */ public Cookie getCookie(String cookieName) { // 這里需要獲取request對象 TODO HttpServletRequest request = null; // 獲取所有的cookie Cookie[] array = request.getCookies(); if (array != null) { for (Cookie cookie : array) { if (cookieName.equals(cookie.getName())) { return cookie; } } } return null; }
方式二:獲取cookie值
/** * 獲取cookie對應的值 * @param cookieName cookie名稱 * @return cookie對應的值 */ public String getCookieValue(String cookieName) { // 這里需要獲取request對象 TODO HttpServletRequest request = null; // 獲取所有的cookie Cookie[] array = request.getCookies(); if (array != null) { for (Cookie cookie : array) { if (cookieName.equals(cookie.getName())) { // 中文需要編碼,所以這里需要解碼 return AESEncryptUtil.decrypt(cookie.getValue()); } } } return ""; }
2.添加cookie
/** * 添加cookie * @param cookieName cookie名 * @param cookieValue cookie值 * @param maxAge 有效期,單位:秒 * 不設置,傳0,默認為:session會話關閉時,cookie失效,即關閉瀏覽器 * @param path 可訪問該cookie的路徑 * 不設置,傳"",默認為:當前請求de路徑 */ public void addCookie(String cookieName, String cookieValue, int maxAge, String path) { // 這里需要獲取request對象 TODO HttpServletRequest request = null; HttpServletResponse response = null; // cookie值進行編碼 cookieValue = AESEncryptUtil.encrypt(cookieValue); // 創建cookie Cookie cookie = new Cookie(cookieName, cookieValue); // 默認為:session會話關閉失效,即關閉瀏覽器 if (0 != maxAge) { cookie.setMaxAge(maxAge); } //默認為:當前請求de路徑 if (!"".equals(path)) { // 判斷path是否以/開頭,沒有就加上 path = !path.startsWith("/") ? "/" + path : path; // 項目根路徑 String webAppPath = request.getContextPath(); // 判斷即將設置的路徑是否以本項目的上下文開頭 //(不加項目頭,則該cookie的可訪問路徑將脫離項目,也就是說在項目內永遠無法訪問到它。) path = !path.startsWith(webAppPath) ? webAppPath + path : path; cookie.setPath(path); } response.addCookie(cookie); }
3.修改cookie
/** * 修改cookie * @param cookieName cookie名 * @param cookieValue cookie值 * @param maxAge 有效期,單位:秒 * 不設置,傳0,默認為:session會話關閉時,cookie失效,即關閉瀏覽器(如果想要刪除,調delCookie()) * 禁止傳path參數,因為傳的話,還要限制最終結果是實現了修改而不是添加(路徑不同,將導致新增一個cookie) */ public void updateCookie(String cookieName, String cookieValue, int maxAge) { // 這里需要獲取request對象 TODO HttpServletRequest request = null; HttpServletResponse response = null; Cookie[] array = request.getCookies(); if (array != null) { for (Cookie cookie : array) { if (cookieName.equals(cookie.getName())) { if (0 != maxAge) { cookie.setMaxAge(maxAge); } // 只有獲取該cookie所在路徑,才能實現對應的修改 cookie.setPath(cookie.getPath()); response.addCookie(cookie); } break; } } }
4.刪除cookie
方式一:刪除客戶端指定cookie
/** * 清除客戶端指定cookie * @param cookieName 要刪除的cookie的名稱 */ public void delCookie(String cookieName) { // 這里需要獲取request對象 TODO HttpServletRequest request = null; HttpServletResponse response = null; Cookie[] array = request.getCookies(); if (array != null) { for (Cookie cookie : array) { if (cookieName.equals(cookie.getName())) { // 當maxAge為0時,表示立即刪除Cookie。 cookie.setMaxAge(0); // 只有獲取該cookie所在路徑,才能實現對應的刪除 cookie.setPath(cookie.getPath()); response.addCookie(cookie); } break; } } }
方式二:刪除客戶端所有的cookie
/** * 清除客戶端所有的cookie */ public void clear() { // 這里需要獲取request對象 TODO HttpServletRequest request = null; HttpServletResponse response = null; Cookie[] array = request.getCookies(); if (array != null) { for (Cookie cookie : array) { // 當maxAge為0時,表示立即刪除Cookie。 cookie.setMaxAge(0); // 只有獲取該cookie所在路徑,才能實現對應的刪除 cookie.setPath(cookie.getPath()); response.addCookie(cookie); } } }