【原】cookie小結


    前記:前段時間搞一個活動,開發的時間被嚴重壓縮,忙到飛起,以致於都沒怎么寫文章了,內疚.

 

    2月份參加了一場面試,有一些關於cookie的問題回答的不是很好,所以這篇文章我們來對cooKie做一個探討和總結,查漏補缺。其實本文很早之前都寫的差不多了,不過關於cookie跨域方面,查了比較多的資料,始終沒有一個太好的結果,所以本文一直沒有發布。

  本文的很多內容都是參考網上的資料,可以說是好幾篇資料的集合,畢竟是總結嘛,就是將自己覺得有用的東西集合在一起。

 

什么是cookie      

      官方定義:Netscape官方文檔中的定義為,Cookie是指在HTTP協議下,服務器或腳本可以維護客戶端計算機上信息的一種方式 。通俗地說,Cookie是一種能夠讓網站Web服務器把少量數據儲存到客戶端的硬盤或內存里,或是從客戶端的硬盤里讀取數據的一種技術。 Cookie文件則是指在瀏覽某個網站時,由Web服務器的CGI腳本創建的存儲在瀏覽器客戶端計算機上的一個小文本文件,其格式為:用戶名@網站地址 [數字].txt。

  再通俗一點的講,由於HTTP是一種無狀態的協議,服務器單從網絡連接上無從知道客戶身份。怎么辦呢?就給客戶端們頒發一個通行證,每人一個,無論誰訪問都必須攜帶自己通行證。這樣服務器就能從通行證上確認客戶身份了。

cookie的作用 

     HTTP協議是一種無狀態、無連接的協議,不能在服務器上保持一次會話的連續狀態信息。Cookie的作用是記錄用戶的有關信息,它最根本的用途是幫助Web站點保存有關訪問者的信息。如身份識別號碼ID、密碼、瀏覽過的網頁、停留的時間、用戶在Web站點購物的方式或用戶訪問該站點的次數等,當用戶再次鏈接Web服務器時,瀏覽器讀取Cookie信息並傳遞給Web站點。   

cookie的屬性

  我們先來看一張圖:

   在谷歌瀏覽器開發者模式中,我們可以看到網站的cookie,所以,相應的,我們就可以知道cookie的一些屬性了,接下來介紹Cookie中的一些屬性

如圖所示,cookie具有的屬性有 Name、value、Domain、path、Expires/Max-Age、Size、HTTP、Secure等等,我們接下來詳細了解了解

Name:

該Cookie的名稱,一旦創建,名稱便不可更改

value: 

該Cookie的值,如果值為Unicode字符,需要為字符編碼,如果值為二進制數據,則需要使用BASE64編碼

domain

可以訪問該Cookie的域名。如果設置為”.google.com”,則所有以”google.com”結尾的域名都可以訪問該Cookie。注意第一個字符必須為“.

這個domain稍作解釋:

    非頂級域名,如二級域名或者三級域名,設置的cookie的domain只能為頂級域名或者二級域名或者三級域名本身,不能設置其他二級域名的cookie,否則cookie無法生成。

    頂級域名只能設置domain為頂級域名,不能設置為二級域名或者三級域名,否則cookie無法生成。

    二級域名能讀取設置了domain為頂級域名或者自身的cookie,不能讀取其他二級域名domain的cookie。所以要想cookie在多個二級域名中共享,需要設置domain為頂級域名,這樣就可以在所有二級域名里面或者到這個cookie的值了。
頂級域名只能獲取到domain設置為頂級域名的cookie,其他domain設置為二級域名的無法獲取。

Path:

path字段為可以訪問此cookie的頁面路徑。 比如domain是abc.com,  path是/detail,那么只有/detail 路徑下的頁面可以讀取此cookie。 

Expires/Max-Age: 

    該Cookie失效時間,單位秒。如果為正數,則Cookie在maxAge秒之后失效。

    如果為負數,該Cookie為臨時Cookie,關閉瀏覽器即失效,瀏覽器也不會以任何形式保存Cookie.

    如果為0,表示刪除Cookie。默認是-1

Size:

cookie的大小

http: 

   cookie的httponly屬性。若此屬性為true,則只有在http請求頭中會帶有此cookie的信息,而不能通過document.cookie來訪問此cookie。

   比如截圖中的__jsluid

secure:

  設置是否只能通過https來傳遞此條cookie

cookie的特性

    1、一個瀏覽器針對一個網站最多存20個Cookie,瀏覽器一般只允許存放300個Cookie

      2、每個Cookie的長度不能超過4KB(稀缺)。但不同的瀏覽器實現的不同

      3、Cookie的不可跨域名性。

     例如:Cookie在客戶端是由瀏覽器來管理的,瀏覽器能夠保證Google只會操作Google的Cookie而不會操作Baidu的Cookie,從而保證用戶的隱私安全。

cookie的分類 

cookie有兩種類型:

  • 臨時Cookie(會話Cookie)
  • 永久Cookie

    不設置過期時間,則表示這個cookie生命周期為瀏覽器會話期間,只要關閉瀏覽器窗口,cookie就消失了。這種生命期為瀏覽會話期的cookie被稱為會話cookie。會話cookie一般不保存在硬盤上而是保存在內存里。可以類比於本地存儲的sessionstore

   設置了過期時間,瀏覽器就會把cookie保存到硬盤上,關閉后再次打開瀏覽器,這些cookie依然有效直到超過設定的過期時間。

   存儲在硬盤上的cookie可以在不同的瀏覽器進程間共享,比如兩個IE窗口。而對於保存在內存的cookie,不同的瀏覽器有不同的處理方式。可以類比於本地存儲的localstore

cookie的操作

cookie的發送:

     服務器端像客戶端發送Cookie是通過HTTP響應報文實現的,在Set-Cookie中設置需要像客戶端發送的cookie,cookie格式如下:

Set-Cookie: "name=value;domain=.domain.com;path=/;expires=Sat, 11 Jun 2016 11:29:42 GMT;HttpOnly;secure"
其中name=value是必選項,其它都是可選項。

  客戶端的話用js即可操作,由於現在客戶端設置大部分用H5的本地存儲localstore和sessionstore多一點,所以客戶端的這里不做介紹

 

cookie的讀取

  這里介紹的js來讀取cookie,可以直接使用下面的方法,其實就是用document.cookie:

function getCookie(name){
    var cookieName=encodeURIComponent(name)+"=",
    cookieStart=document.cookie.indexOf(cookieName),
    cookieValue=null;
    if(cookieStart>-1){
        var cookieEnd=document.cookie.indexOf(";",cookieStart);
        if(cookieEnd==-1){
            cookieEnd=document.cookie.Length;
        }
        cookieValue=decodeURIComponent(document.cookie.substring(cookieStart+document.cookie.length,cookieEnd));
    }
    return cookieValue;
}

 

cookie的修改與刪除

      Cookie並不提供修改、刪除操作。如果要修改某個Cookie,只需要新建一個同名的Cookie,添加到response中覆蓋原來的Cookie。

      如果要刪除某個Cookie,只需要新建一個同名的Cookie,並將maxAge設置為0,並添加到response中覆蓋原來的Cookie。注意是0而不是負數。

Cookie的實現原理

   Cookie實際上是一小段的文本信息。客戶端請求服務器,如果服務器需要記錄該用戶狀態,就使用response向客戶端瀏覽器頒發一個Cookie。客戶端瀏覽器會把Cookie保存起來。當瀏覽器再請求該網站時,瀏覽器把請求的網址連同該Cookie一同提交給服務器。服務器檢查該Cookie,以此來辨認用戶狀態。服務器還可以根據需要修改Cookie的內容。如下圖所示:

這個跟其實跟瀏覽器你器緩存有點類似,具體的過程我們可以分解分解:

(1)客戶端在瀏覽器的地址欄中鍵入Web服務器的URL,瀏覽器發送讀取網頁的請求。 

(2)服務器接收到請求后,產生一個Set-Cookie報頭,放在HTTP報文中一起回傳客戶端,發起一次會話。 

(3)客戶端收到應答后,若要繼續該次會話,則將Set-Cook-ie中的內容取出,形成一個Cookie.txt文件儲存在客戶端計算機里。

(4)當客戶端再次向服務器發出請求時,瀏覽器先在電腦里尋找對應該網站的Cookie.txt文件。如果找到,則根據此Cookie.txt產生Cookie報頭,放在HTTP請求報文中發給服務器。

(5)服務器接收到包含Cookie報頭的請求,檢索其Cookie中與用戶有關的信息,生成一個客戶端所請示的頁面應答傳遞給客戶端。 瀏覽器的每一次網頁請求,都可以傳遞已存在的Cookie文件,例如,瀏覽器的打開或刷新網頁操作。

Cookie的安全問題 

     通常cookie信息都是使用http連接傳遞數據,這種傳遞方式很容易被查看,而且js里面直接有一個document.cookie方法,可以直接獲取到用戶的cooie,所以cookie存儲的信息容易被竊取。假如cookie中所傳遞的內容比較重要,那么就要求使用加密的數據傳輸。

  如何來防范cookie的安全呢?有以下幾種方法:

(1)HttpOnly屬性
   如果在Cookie中設置了"HttpOnly"屬性,那么通過程序(JS腳本、Applet等)將無法讀取到Cookie信息,這樣能有效的防止XSS攻擊。

(2)secure屬性
    當設置為true時,表示創建的 Cookie 會被以安全的形式向服務器傳輸,也就是只能在 HTTPS 連接中被瀏覽器傳遞到服務器端進行會話驗證,如果是 HTTP 連接則不會傳遞該信息,所以不會被盜取到Cookie 的具體內容。

 

我們再來看看一道經典的面試題:

登錄時候用cookie的話,安全性問題怎么解決?

這個問題,網上找了比較久的答案,比較滿意的有兩種答案(答案是網上找的)

第一種是:

    把用戶對象(包含了用戶ID、用戶名、是否登錄..)序列化成字符串再加密存入Cookie。

    密鑰是:客戶端IP+瀏覽器Agent+用戶標識+固定的私有密鑰

    當cookie被竊取后,只要任一信息不匹配,就無法解密cookie,進而也就不能登錄了。

    這樣做的缺點是IP不能變動、頻繁加密解密會加重CPU負擔

 第二種是:

將用戶的認證信息保存在一個cookie中,具體如下: 
1.cookie名:uid。推薦進行加密,比如MD5(‘站點名稱’)等。 
2.cookie值:登錄名|有效時間Expires|hash值。hash值可以由”登錄名+有效時間Expires+用戶密碼(加密后的)的前幾位 +salt” (salt是保證在服務器端站點配置文件中的隨機數)

這樣子設計有以下幾個優點: 
1.即使數據庫被盜了,盜用者還是無法登錄到系統,因為組成cookie值的salt是保證在服務器站點配置文件中而非數據 庫。 
2.如果賬戶被盜了,用戶修改密碼,可以使盜用者的cookie值無效。 
3.如果服務器端的數據庫被盜了,通過修改salt值可以使所有用戶的cookie值無效,迫使用戶重新登錄系統。 
4.有效時間Expires可以設置為當前時間+過去時間(比如2天),這樣可以保證每次登錄的cookie值都不一樣,防止盜用者 窺探到自己的cookie值后作為后門,長期登錄。

cookie跨地址,跨域問題以及解決方案

      cookie是不能跨域訪問的,那么,假如需要跨域來進行cookie的訪問和傳遞,該怎么辦呢?查找了比較多的資料,比較少這方面的資料,

在cookie跨域這個問題上,前端能做的不多,很多都是需要和后端一起配合來完成。

  總結了下面的幾種方法,具體的實現過程這里沒有寫,可以點擊我提供的鏈接自己看看。

      前2種具體的實現方法可以點擊看這里:點我

1、nginx方向代理:

  反向代理(Reverse Proxy)方式是指以代理服務器來接受Internet上的連接請求,然后將請求轉發給內部網絡上的服務器;並將從服務器上得到的結果返回給Internet上請求連接的客戶端,此時代理服務器對外就表現為一個服務器。

  反向代理服務器對於客戶端而言它就像是原始服務器,並且客戶端不需要進行任何特別的設置。客戶端向反向代理 的命名空間(name-space)中的內容發送普通請求,接着反向代理將判斷向何處(原始服務器)轉交請求,並將獲得的內容返回給客戶端,就像這些內容 原本就是它自己的一樣。

2、jsonp方法:

  這個方法和我們平時處理js跨域的jsonp方法一樣。具體實現方法可以看看淘寶的解決方法,點我

3、nodejs的superagent

4、iframe方法:

比如有個www.a.com/index.html的頁面,往www.b.com/index.html的頁面傳遞cookie

www.a.com/index.html這樣寫:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>我是a頁面</title>
</head>
<body>
    
</body>
<script type="text/javascript">
document.cookie = "name=" + "value;" + "expires=" + "datatime;" + "domain=" + "" + "path=" + "/path" + "; secure";
//name Cookie名字
//value Cookie值
//expires 有效期截至(單位毫秒)
//path 子目錄
//domain 有效域
//secure 是否安全
window.location = "http://www.b.com/index.html?" + document.cookie;  //跳轉到b頁面
</script>
</html>

www.b.com/index.html 這樣寫:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>我是b頁面</title>
</head>
<body>
   <iframe src='http://www.a.com/index.html' width='100' height='100' style="display:none"></iframe>
</body>
<script type="text/javascript">
var url = window.location.toString();//獲取地址
var get = url.substring(url.indexOf("abc"));//獲取變量和變量值
var idx = get.indexOf("=");//獲取變量名長度
if (idx != -1) {
   var name = get.substring(0, idx);//獲取變量名
   var val = get.substring(idx + 1);//獲取變量值
   setCookie(name, val, 1);//創建Cookie
}
</script>
</html>

 

 

備注:本文主要是查找了網上比較多的資料來總結cookie的一些知識,文筆有限,有誤之處,歡迎指出

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM