cookie簡(jiǎn)介
1. 定義
cookie是由服務(wù)器發(fā)送給客戶(hù)端(瀏覽器)的小量信息。
2. 作用
cookie是鍵值對(duì)形式存儲(chǔ)的少量信息,那它有什么作用呢?
我們知道,平時(shí)上網(wǎng)時(shí)都是使用無(wú)狀態(tài)的HTTP協(xié)議傳輸出數(shù)據(jù),這意味著客戶(hù)端與服務(wù)端在數(shù)據(jù)傳送完成后就會(huì)中斷連接。這時(shí)我們就需要一個(gè)一直保持會(huì)話(huà)連接的機(jī)制。在session出現(xiàn)前,cookie就完全充當(dāng)了這種角色。也就是,cookie的小量信息能幫助我們跟蹤會(huì)話(huà)。一般該信息記錄用戶(hù)身份。
當(dāng)然cookie也常記錄跟蹤購(gòu)物車(chē)的商品信息(如數(shù)量)、記錄用戶(hù)訪(fǎng)問(wèn)次數(shù)等。
3. 原理
客戶(hù)端請(qǐng)求服務(wù)器時(shí),如果服務(wù)器需要記錄該用戶(hù)狀態(tài),就使用response向客戶(hù)端瀏覽器頒發(fā)一個(gè)Cookie。而客戶(hù)端瀏覽器會(huì)把Cookie保存起來(lái)。當(dāng)瀏覽器再請(qǐng)求服務(wù)器時(shí),瀏覽器把請(qǐng)求的網(wǎng)址連同該Cookie一同提交給服務(wù)器。服務(wù)器通過(guò)檢查該Cookie來(lái)獲取用戶(hù)狀態(tài)。
4.添加cookie示例
獲取客戶(hù)端的Cookie時(shí),只能獲取name與value屬性,其它屬性都不會(huì)被提交。
Cookie c = new Cookie("username","peter");// 新建一個(gè)Cookie對(duì)象
c.setMaxAge(24*60*60); // 設(shè)置過(guò)期時(shí)間1天,以秒為單位
response.addCookie(c); // 保存cookie到客戶(hù)端
5.刪除cookie示例
刪除某個(gè)Cookie時(shí),只需要新建一個(gè)只有maxAge和value不一樣的同名Cookie,然后添加到response中覆蓋原來(lái)的Cookie
Cookie cookie = new Cookie("username","peter");// 新建Cookie
cookie.setMaxAge(0); // 設(shè)置生命周期為0,表示將要?jiǎng)h除
response.addCookie(cookie); // 執(zhí)行添加后就從response里刪除了
6.修改cookie示例
修改某個(gè)Cookie時(shí),只需要新建一個(gè)只有value屬性不一樣的同名Cookie,然后添加到response中覆蓋原來(lái)的Cookie
Cookie cookie = new Cookie("username","joker");// 新建Cookie
cookie.setMaxAge(24*60*60); // 設(shè)置生命周期
response.addCookie(cookie); // 執(zhí)行添加后就從response里覆蓋修改了
注意:修改、刪除Cookie時(shí),新建的Cookie除value、maxAge之外的所有屬性,例如name、path、domain等,都要與原Cookie完全一樣。否則,瀏覽器將視為兩個(gè)不同的Cookie而不會(huì)覆蓋之前的Cookie,從而導(dǎo)致修改、刪除失敗。
Cookie類(lèi)的各方法詳解
Cookie類(lèi)在javax.servlet.http.Cookie包中
對(duì)應(yīng)的getter方法我就不講了。
如果cookie值為Unicode字符,需要為字符編碼。如果cookie值為二進(jìn)制數(shù)據(jù),則需要使用BASE64編碼
cookie的setPath()和setDomain()方法
默認(rèn)情況下cookie只能在一個(gè)應(yīng)用中共享,即一個(gè)cookie只能由創(chuàng)建它的應(yīng)用獲得。
設(shè)置同一服務(wù)器內(nèi)的cookie使用范圍用setPath
c.setPath(“/”),使同一服務(wù)器內(nèi)所有應(yīng)用都可訪(fǎng)問(wèn)到該Cookie:
Cookie c = new Cookie("name","peter");
c.setMaxAge(24*60*60);
c.setPath("/");//同一服務(wù)器內(nèi)所有應(yīng)用都可訪(fǎng)問(wèn)到該Cookie
response.addCookie(c); //保存cookie到客戶(hù)端
1.如果同一服務(wù)器內(nèi)有兩個(gè)應(yīng)用agx1.0和agx2.0
當(dāng)我們?cè)赼gx1.0里有c.setPath(“/agx2.0/”);時(shí),該cookie就只能在agx2.0下面能獲取到,就連創(chuàng)建該cookie的agx1.0也獲取不到。
2.如果在agx1.0里有c.setPath(“/agx2.0/abc/”);時(shí),則只能在agx2.0/abc下面才能獲得該cookie,即使在agx2.0下面也不能獲取到。
cookie的跨域
1.正常情況下Cookie不可跨域名,如域名www.google.com頒發(fā)的Cookie不會(huì)被提交到域名www.baidu.com去。這是由Cookie的隱私安全機(jī)制決定的。即使在同一個(gè)一級(jí)域名下的兩個(gè)二級(jí)域名如www.agx.com和images.agx.com也不能交互使用Cookie,因?yàn)槎叩挠蛎⒉粐?yán)格相同。如果想所有agx.com名下的二級(jí)域名都可以使用該Cookie,則需要設(shè)置Cookie的domain參數(shù)為”.agx.com”,例如:
Cookie cookie = new Cookie("name","peter"); // 新建Cookie
cookie.setDomain(".agx.com"); // 設(shè)置域名
cookie.setPath("/"); // 設(shè)置路徑
cookie.setMaxAge(Integer.MAX_VALUE); // 設(shè)置有效期為永久
response.addCookie(cookie); // 輸出到客戶(hù)端
讀者可以修改本機(jī)C:\WINDOWS\system32\drivers\etc下的hosts文件來(lái)配置多個(gè)臨時(shí)域名,然后使用setCookie.jsp程序來(lái)設(shè)置跨域名Cookie驗(yàn)證domain屬性。
注意:domain參數(shù)必須以點(diǎn)(“.”)開(kāi)始。另外,name相同但domain不同的兩個(gè)Cookie是兩個(gè)不同的Cookie。如果想要兩個(gè)域名完全不同的網(wǎng)站共有Cookie,可以生成兩個(gè)name相同的Cookie,domain屬性分別為兩個(gè)域名。
2.若A服務(wù)器的域名為:adv.audiogroup.com,有應(yīng)用名為:agx1.0; B服務(wù)器的域名為:agx.com,有應(yīng)用名為:agx2.0。
在A(yíng)服務(wù)器的agx1.0應(yīng)用下設(shè)置cookie如下:
Cookie cookie = new Cookie("name","peter"); // 新建Cookie
cookie.setDomain(".agx.com"); // 設(shè)置域名
cookie.setPath("/"); // 設(shè)置路徑
cookie.setMaxAge(Integer.MAX_VALUE); // 設(shè)置有效期為永久
response.addCookie(cookie); // 輸出到客戶(hù)端
這時(shí),在B服務(wù)器下的agx2.0應(yīng)用和agx1.0里都能取到上面的Cookie。
注:輸入U(xiǎn)RL訪(fǎng)問(wèn)agx2.0時(shí),必須輸入域名才能獲取其它服務(wù)器共享給它的cookie,如:
輸入http://images.agx.com:8080/agx2.0,可以獲取agx1.0在客戶(hù)端設(shè)置的cookie
輸入:http://localhost:8080/agx2.0則不可以獲得cookie。
setPath()與setDomain()的區(qū)別?
setDomain()主要用來(lái)確定兩個(gè)不同名稱(chēng)但后綴相同的網(wǎng)站地址是否能使用同一個(gè)Cookie。
例: www.agx.com和 bbs.agx.com只要有cookie.setDomain(“.zjut.edu.cn”);就都能使用該cookie
setPath()主要用來(lái)確定地址里什么后綴下能夠使用這個(gè)Cookie
歸結(jié)起來(lái)就是:setDomain決定允許訪(fǎng)問(wèn)Cookie的域名,而setPath決定允許訪(fǎng)問(wèn)Cookie的路徑(ContextPath)
獲取用戶(hù)請(qǐng)求里的cookie
Cookie[] cookie = request.getCookies();//獲取的是請(qǐng)求里的所有cookie組成的數(shù)組
for(int i=0;i<cookie.length;i++){
if("name".equals(cookie[i].getName())){
System.out.println(cookie[i].getValue());//得到peter
break;
}
}
解決cookie里中文亂碼問(wèn)題
Cookie中要保存中文只能編碼。一般使用UTF-8編碼即可。不推薦使用GBK等中文編碼,因?yàn)闉g覽器不一定支持,而且JavaScript也不支持GBK編碼。
Cookie不僅可以使用ASCII字符與Unicode字符,還可以使用二進(jìn)制數(shù)據(jù)。例如在Cookie中使用數(shù)字證書(shū),提供安全度。使用二進(jìn)制數(shù)據(jù)時(shí)也需要進(jìn)行編碼(如用BASE64編碼保存二進(jìn)制圖片)。由于瀏覽器每次請(qǐng)求都會(huì)帶著Cookie,因此Cookie內(nèi)容不宜過(guò)多,所以一般不會(huì)在Cookie中存儲(chǔ)二進(jìn)制的內(nèi)容
JS操作Cookie
Cookie是保存在客戶(hù)端的,所以瀏覽器可以使用腳本(JS)等操作Cookie。
<script language=javascript>
//添加cookie
function setCookie(name,value,time){
var date= new Date();
date.setDate(date.getDate()+time);
document.cookie = name+"="+value+";expires="+date;
}
//獲得cookie
function getCookie(name){
var arr = document.cookie.split(";");
for(var i=0; i<arr.length; i++){
var arr2 = arr[i].split("=");
if(arr2[0] == name){
return arr2[1];
}
}
return null;
}
//刪除cookie
function removeCookie(name){
setCookie(name,"",0)
}
</script>
W3C標(biāo)準(zhǔn)的瀏覽器會(huì)阻止JavaScript讀寫(xiě)任何不屬于自己網(wǎng)站的Cookie。即A網(wǎng)站的JavaScript代碼里獲取不到B網(wǎng)站的Cookie。
使用cookie記住密碼
方案1:
直接把用戶(hù)名與密碼都保持到Cookie中,下次訪(fǎng)問(wèn)時(shí)檢查Cookie中的用戶(hù)名與密碼,與數(shù)據(jù)庫(kù)比較。這是一種比較危險(xiǎn)的選擇,一般不把密碼等重要信息保存到Cookie中。
方案2:
把密碼加密后保存到Cookie中,下次訪(fǎng)問(wèn)時(shí)解密并與數(shù)據(jù)庫(kù)比較。這種方案略微安全一些。如果不希望保存密碼,還可以把登錄的時(shí)間戳保存到Cookie與數(shù)據(jù)庫(kù)中,到時(shí)只驗(yàn)證用戶(hù)名與登錄時(shí)間戳就可以了。
方案3:
實(shí)現(xiàn)方式是把賬號(hào)按照一定的規(guī)則(密鑰)加密后,連同賬號(hào)一塊保存到Cookie中。下次訪(fǎng)問(wèn)時(shí)只需要判斷賬號(hào)的加密規(guī)則是否相同即可。
加 密:
String userName = request.getParameter("userName");//獲取用戶(hù)名
Md5Hash psw = new Md5Hash(userName, "peter.com", 2);//以peter.com為密鑰加密
//將用戶(hù)名添加進(jìn)cookie并發(fā)送給客戶(hù)端
Cookie userCookie = new Cookie("userName",userName);
userCookie.setMaxAge(7*24*60*60);
response.addCookie(userCookie);
//將密鑰生成的密文加進(jìn)cookie并發(fā)送給客戶(hù)端
Cookie c = new Cookie("key",psw.toString());
c.setMaxAge(7*24*60*60);
response.addCookie(c);
解密:
String usreName = null;
String key = null;
Cookie[] cookie = request.getCookies();
if(cookie !=null){
for(Cookie c:cookie){ // 遍歷Cookie
if("userName".equals(c.getName())
userName = c.getValue();
if("key".equals(c.getName())
key= cookie.getValue();
}
}
if(userName != null && key != null){
String secrect = new Md5Hash(userName, "peter.com", 2);
if(key.equals(secrect )){//加密規(guī)則正確,說(shuō)明已經(jīng)登錄
//...
//....省略后續(xù)處理
}
}
由上面可知,如果將密碼加密后存進(jìn)cookie后,當(dāng)我們下次訪(fǎng)問(wèn)登錄頁(yè)時(shí),密碼框里的密碼將不是用戶(hù)真正的密碼。
原文鏈接:https://blog.csdn.net/qq_29132907/article/details/80390792