好程式設計師Web前端教程分享新手應該瞭解的Cookie知識!

好程式設計師IT發表於2019-10-24

  好程式設計師Web 前端教程分享 新手應該瞭解的Cookie 知識!

  一、Cookie 的出現

 

  瀏覽器和伺服器之間的通訊少不了HTTP 協議,但是因為 HTTP 協議是無狀態的,所以伺服器並不知道上一次瀏覽器做了什麼樣的操作,這樣嚴重阻礙了互動式 Web 應用程式的實現。

 

  二、Cookie 的傳輸

 

  伺服器端在實現Cookie 標準的過程中,需要對任意 HTTP 請求傳送 Set-CookieHTTP 頭作為響應的一部分:

 

  1.Set-Cookie:name=value;expires=Tue,03-Sep-201914:10:21GMT;path=/;domain=.xxx.com;

 

  瀏覽器端會儲存這樣的Cookie ,並且為之後的每個請求新增 CookieHTTP 請求頭髮送回伺服器:

 

  1.Cookie:name=value

 

  伺服器透過驗證Cookie 值,來判斷瀏覽器傳送請求屬於哪一個使用者。

 

  三、瀏覽器中的Cookie

 

  瀏覽器中的Cookie 主要由以下幾部分組成:

 

  ·名稱: Cookie 唯一的名稱,必須經過 URL 編碼處理。 ( 同名會出現覆蓋的情況 )

 

  ·值:必須經過 URL 編碼處理。

 

  ·域 (domain) :預設情況下 cookie 在當前域下有效,你也可以設定該值來確保對其子域是否有效。

 

  ·路徑 (path) :指定 Cookie 在哪些路徑下有效,預設是當前路徑下。

 

  ·失效時間 (expires) :預設情況下,瀏覽器會話結束時會自動刪除 Cookie; 也可以設定一個 GMT 格式的日期,指定具體的刪除日期 ; 如果設定的日期為以前的日期,那麼 Cookie 會立即刪除。

 

  ·安全標誌 (secure) :指定之後只允許 Cookie 傳送給 https 協議。

 

  瀏覽器在傳送請求時,只會將名稱與值新增到請求頭的Cookie 欄位中,傳送給服務端。

 

  瀏覽器提供了一個非常蹩腳的API 來操作 Cookie

 

  1.document.cookie

 

  透過上述方法可以對該Cookie 進行寫操作,每一次只能寫入一條 Cookie 字串:

 

  1.document.cookie='a=1;secure;path=/'

 

  透過該方法還可以進行Cookie 的讀操作:

 

  1.document.cookie//"a=1"

 

  由於上述方法操作Cookie 非常的不直觀,一般都會寫一些函式來簡化 Cookie 讀取、設定和刪除操作。

 

  對於Cookie 的設定操作中,需要以下幾點:

 

  對於名稱和值進行URL 編碼處理,也就是採用 JavaScript 中的 encodeURIComponent() 方法 ;expires 要求傳入 GMT 格式的日期,需要處理為更易書寫的方式,比如:設定秒數的方式 ; 注意只有的屬性名的 secure;

 

  每一段資訊需要採用分號加空格。

 

  1.functionsetCookie(key,value,attributes){

 

  2.if(typeofdocument==='undefined'){

 

  3.return

 

  4.}

 

  5.attributes=Object.assign({},{

 

  6.path:'/'

 

  7.},attributes)

 

  8.

 

  9.let{domain,path,expires,secure}=attributes

 

  10.

 

  11.if(typeofexpires==='number'){

 

  12.expires=newDate(Date.now()+expires*1000)

 

  13.}

 

  14.if(expiresinstanceofDate){

 

  15.expires=expires.toUTCString()

 

  16.}else{

 

  17.expires=''

 

  18.}

 

  19.

 

  20.key=encodeURIComponent(key)

 

  21.value=encodeURIComponent(value)

 

  22.

 

  23.letcookieStr=`${key}=${value}`

 

  24.

 

  25.if(domain){

 

  26.cookieStr+=`;domain=${domain}`

 

  27.}

 

  28.

 

  29.if(path){

 

  30.cookieStr+=`;path=${path}`

 

  31.}

 

  32.

 

  33.if(expires){

 

  34.cookieStr+=`;expires=${expires}`

 

  35.}

 

  36.

 

  37.if(secure){

 

  38.cookieStr+=`;secure`

 

  39.}

 

  40.

 

  41.return(document.cookie=cookieStr)

 

  42.}

 

  Cookie 的讀操作需要注意的是將名稱與值進行 URL 解碼處理,也就是呼叫 JavaScript 中的 decodeURIComponent() 方法:

 

  1.functiongetCookie(name){

 

  2.if(typeofdocument==='undefined'){

 

  3.return

 

  4.}

 

  5.letcookies=[]

 

  6.letjar={}

 

  7.document.cookie&&(cookies=document.cookie.split(';'))

 

  8.

 

  9.for(leti=0,max=cookies.length;i<max;i++){

 

  10.let[key,value]=cookies[i].split('=')

 

  11.key=decodeURIComponent(key)

 

  12.value=decodeURIComponent(value)

 

  13.jar[key]=value

 

  14.if(key===name){

 

  15.break

 

  16.}

 

  17.}

 

  18.

 

  19.returnname?jar[name]:jar

 

  20.}

 

  最後一個清除的方法就更加簡單了,只要將失效日期(expires) 設定為過去的日期即可:

 

  1.functionremoveCookie(key){

 

  2.setCookie(key,'',{expires:-1})

 

  3.}

 

  介紹Cookie 基本操作的封裝之後,還需要了解瀏覽器為了限制 Cookie 不會被惡意使用,規定了 Cookie 所佔磁碟空間的大小以及每個域名下 Cookie 的個數。

 

  四、服務端的Cookie

 

  相比較瀏覽器端,服務端執行Cookie 的寫操作時,是將拼接好的 Cookie 字串放入響應頭的 Set-Cookie 欄位中 ; 執行 Cookie 的讀操作時,則是解析 HTTP 請求頭欄位 Cookie 中的鍵值對。

 

  與瀏覽器最大的不同,在於服務端對於Cookie 的安全性操碎了心

 

  signed

 

  當設定signed=true 時,服務端會對該條 Cookie 字串生成兩個 Set-Cookie 響應頭欄位:

 

  1.Set-Cookie:lastTime=2019-03-05T14:31:05.543Z;path=/;httponly

 

  2.Set-Cookie:lastTime.sig=URXREOYTtMnGm0b7qCYFJ2Db400;path=/;httponly

 

  這裡透過再傳送一條以.sig 為字尾的名稱以及對值進行加密的 Cookie ,來驗證該條 Cookie 是否在傳輸的過程中被篡改。

 

  httpOnly

 

  服務端Set-Cookie 欄位中新增 httpOnly 屬性,當服務端在返回的 Cookie 資訊中含有 httpOnly 欄位時,開發者是不能透過 JavaScript 來操縱該條 Cookie 字串的。

 

  這樣做的好處主要在於面對XSS(Cross-sitescripting) 攻擊時,駭客無法拿到設定 httpOnly 欄位的 Cookie 資訊。

 

  此時,你會發現localStorage 相比較 Cookie ,在 XSS 攻擊的防禦上就略遜一籌了。 sameSite

 

  在介紹這個新屬性之前,首先你需要明白:當使用者從 發起 的請求也會攜帶上 Cookie ,而從 攜帶過來的 Cookie 稱為第三方 Cookie

 

  雖然第三方Cookie 有一些好處,但是給 CSRF(Cross-siterequestforgrey) 攻擊的機會。

 

  為了從根源上解決CSRF 攻擊, sameSite 屬性便閃亮登場了,它的取值有以下幾種:

 

  · strict :瀏覽器在任何跨域請求中都不會攜帶 Cookie ,這樣可以有效的防禦 CSRF 攻擊,但是對於有多個子域名的網站採用主域名儲存使用者登入資訊的場景,每個子域名都需要使用者重新登入,造成使用者體驗非常的差。

 

  · lax :相比較 strict ,它允許從三方網站跳轉過來的時候使用 Cookie

 

  為了方便大家理解sameSite 的實際效果,可以看這個例子:

 

  1.//a.com 服務端會在訪問頁面時返回如下 Cookie

 

  2.cookies.set('foo','aaaaa')

 

  3.cookies.set('bar','bbbbb')

 

  4.cookies.set('name','cccccc')

 

  5.

 

  6.//b.com 服務端會在訪問頁面時返回如下 Cookie

 

  7.cookies.set('foo','a',{sameSite:'strict'})

 

  8.cookies.set('bar','b',{sameSite:'lax'})

 

  9.cookies.set('baz','c')

 

  如何現在使用者在a.com 中點選連結跳轉到 b.com ,它的請求頭是這樣的:

 

  1.RequestHeaders

 

  2.

 

  3.Cookie:bar=b;baz=c

 

  五、網站效能最佳化

 

  Cookie 在服務端和瀏覽器的通訊中,主要依靠 HTTP 的響應頭和請求頭傳輸的,所以 Cookie 會佔據一定的頻寬。

 

前面提到瀏覽器會為每一次HTPP 請求自動攜帶上 Cookie 資訊,但是對於同站內的靜態資源,伺服器並不需要處理其攜帶的 Cookie ,這無形中便浪費了頻寬。

 


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69913892/viewspace-2661234/,如需轉載,請註明出處,否則將追究法律責任。

相關文章