【原】cookie小結

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

 

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

  本文的不少內容都是參考網上的資料,能夠說是好幾篇資料的集合,畢竟是總結嘛,就是將本身以爲有用的東西集合在一塊兒。前端

 

什麼是cookie      

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

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

cookie的做用 

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

cookie的屬性

  咱們先來看一張圖:面試

   在谷歌瀏覽器開發者模式中,咱們能夠看到網站的cookie,因此,相應的,咱們就能夠知道cookie的一些屬性了,接下來介紹Cookie中的一些屬性數據庫

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

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的特性

    一、一個瀏覽器針對一個網站最多存20個Cookie,瀏覽器通常只容許存放300個Cookie

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

      三、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種具體的實現方法能夠點擊看這裏:點我

一、nginx方向代理:

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

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

二、jsonp方法:

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

三、nodejs的superagent

四、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的一些知識,文筆有限,有誤之處,歡迎指出

相關文章
相關標籤/搜索