前端分享之cookie的使用及單點登陸

cookie是什麼

cookie的英文意思是餅乾。在計算機術語中指服務端存放在客戶端的一段數據。這段數據在客戶端每次進行http請求時會自動加在http請求報文中的header上;服務端在響應時,能夠對cookie進行設置,並將cookie加入到http響應報文header中。MDN中對cookie的解釋爲:cookie 是一個請求首部,其中含有先前由服務器經過 Set-Cookie 首部投放並存儲到客戶端的 HTTP cookies。
cookie通常存放在對應的域名下,各個瀏覽器對中一個域名下存放的cookie的個數與大小規定不同。下表是不一樣瀏覽器對cookie存放的規定:前端

瀏覽器 chrome Safari Firefox ie
個數 53 無限制 50 50
大小 4097字節 4097字節 4097字節 4095字節
超額處理 剔除最老的cookie 剔除最老的cookie 隨機消除除最新的其餘cookie 剔除最老的cookie

全部瀏覽器都支持cookie功能,咱們能夠直接在瀏覽器中移除cookie與禁用cookie存儲。chrome中的設置爲:設置-高級-隱私設置和安全性-內容設置-cookie。
若是咱們在建立cookie時沒有設置過時時間,即沒有設置expires或者max-age值,則該cookie只存在與會話中,此時,cookie存儲在瀏覽器的內存中,關閉瀏覽器時cookie自動消失。若是設置了過時時間,則cookie存儲在用戶的硬盤上。
在windows OS下chrome存放cookie的路徑是C:Documents and SettingsAdministratorLocal SettingsApplication DataGoogleChromeUser Data,firefox的存放路徑是:C:Documents and SettingsAdministratorLocal SettingsApplication DataMozillaFirefoxProfilesznyzv8y6.defaultOfflineCache
在mac下chrome的存儲路徑爲:~/library/application support/google/chrome;
Safari的存儲路徑爲:~/library/cookies;node

cookie的工做原理

咱們知道http協議是一種無狀態的協議,在web應用程序中,經過http協議進行數據交互,交互完畢後,客戶端與服務端的鏈接就斷開。再次交互須要創建新的鏈接。這種鏈接沒法記錄用戶的狀態,cookie能夠彌補HTTP協議無狀態的不足。服務器給客戶端們頒發一個通行證,不管誰訪問都必須攜帶本身通行證,這樣服務器就能從通行證上確認客戶身份了。這就是Cookie的工做原理。jquery

clipboard.png

上圖展現了cookie的工做原理:
(1)第一次用戶登陸的時候,輸入用戶名和密碼信息,服務端接收後進行用戶認證。
(2)服務端經過驗證後,生成一個token以cookie的形式放在http的response header中一塊兒返回給客戶端。
(3)瀏覽器根據是否設置cookie的過時時間判斷該cookie是會話cookie仍是永久cookie,並將cookie存儲在不一樣的位置。
(4)下次進行http請求時,請求頭中會自動攜帶存儲的cookie。
(5)服務端根據請求頭中的cookie裏面的token確認該用戶的身份信息。ios

常見問題

前端主動向後端跨域發送cookie

在解釋這個問題以前先了解一下什麼是跨域。兩個域之間是否是存在跨域問題,主要是根據協議、域名、端口號這三個點進行判斷,只要有一個不同就是跨域。例如:
(1)協議不一樣:http://www.baidu.comhttps://www.baidu.com
(2)域名不一樣:http://www.baidu.comhttp://www.google.com
(3)端口號不一樣: http://www.baidu.com:8080 與http://www.baidu.com:8000
瀏覽器默認狀況下沒法主動跨域向後端發送cookie,須要在前端請求時加入配置項{withCredentials:true}。
jquery:
$.ajax({url:'myurl',method:'GET', xhrFields:{withCredentials:true},success:function(){}});
angular:
$http.get(url, {withCredentials: true})
axios:
axios.defaults.withCredentials = trueweb

前端配置好後還須要在後端進行相關配置:
在response header裏面添加配置項ajax

"Access-Control-Allow-Credentials「, 「true」 
"Access-Control-Allow-Origin", 」yourdomain「

也有一些中間件幫咱們解決跨域問題。例如express中的express-cors,或者koa中的koa-corschrome

方法屬性

前端cookie

設置:express

document.cookie = 'company=eoitek;max-age=10000;domain=eoitek.com;path=/;secure'

其中max-age是cookie的過時時間,是一個相對時間,值的單位是秒,是相對於cookie建立後多少秒才過時。與max-age類似的配置屬性是expires,值爲日期對象的toUTCString()格式,即Thu, 21 Sep 2018 06:10:38 GMT,是指cookie過時的絕對時間。若是max-age和expires都存在,則max-age的優先級更高。domain是咱們設置cookie存放的域,若是沒有設置則爲當前主機的域。path是指cookie存儲的目錄,默認爲當前文件的存儲目錄。secure,加入此配置項,則指定該cookie只能經過https協議進行傳輸。
讀取:axios

document.cookie

讀取全部該域能獲取到的cookie;格式爲‘<key1>=<value1>;<key2>=<value2>;’windows

後端cookie

設置(以node爲例):

var http = require('http');
http.createServer(
  function(req, res) {
    res.setHeader('status', '200 OK');
    res.setHeader('Set-Cookie', 'name=binbinfang;path=/;
    max-age=1000;domain=eoitek.com');
    res.setHeader('Access-Control-Allow-Origin', 'eoitek.com');
    res.setHeader('Access-Control-Allow-Credentials', 'true');
    res.write('Hello World');
    res.end();
}).listen(8888);

console.log('running localhost:8888');

後端cookie比前端cookie多兩個配置項:
httpOnly:設置了 HttpOnly 屬性的 cookie 不能使用 JavaScript 經由 Document.cookie 屬性、XMLHttpRequest 和 Request APIs 進行訪問,以防範跨站腳本攻擊(XSS);
SameSite=Strict
SameSite=Lax
容許服務器設定一則 cookie 不隨着跨域請求一塊兒發送,這樣能夠在必定程度上防範跨站請求僞造攻擊(CSRF)。

注意事項

(1)保存中文cookie
若是須要保存中文cookie,則須要對中文進行UTF-8編解碼,即經過encodeUriComponent()和decodeUriComponent()方。
(2)保存圖片和安全證書
cookie中也能夠保存二進制圖片和安全證書,須要對文件進行base64編碼才能保存。不過建議最好不要將這類文件保存在cookie中。
(3)cookie的更新
只要將key;path;domain一致,則能夠經過改變key對應的value來更新cookie的值。
(4)cookie的刪除
cookie只能更新不能刪除,若是想要刪除一個cookie,則經過更新設置該cookie的max-age=0便可。
(5)cookie的安全性
設置cookie時添加secure。

cookie因爲其設置和取值都是經過字符串的形式進行的。所以,在原生cookie的操做比較麻煩,可經過一些js庫來方便咱們的操做,包括cookies.js和js-cookie

cookie的跨域獲取與單點登陸問題

默認狀況下,cookie是不能跨域訪問的,如在www.google.com域沒法操做和獲取www.baidu.com裏面的cookie,由於他們的一級域不一樣。可是在二級域裏面能夠共享和修改cookie的。即www.baidu.com和baike.baidu.com之間是能夠共享cookie的。據此,能夠實現單點登陸。
單點登陸:多個不一樣系統整合到統一加載個平臺,用戶在任何一個系統登陸後,能夠訪問這個統一加載上的全部系統。登陸以後,用戶的權限和信息再也不受某個系統的限制,即便某個系統出現故障(包括統一加載平臺),其餘系統仍是能正常使用的。這就須要用戶權限等信息保存到客戶端,不受服務器的限制。
例如,咱們有兩個站點,都須要用戶身份認證,要實現單點登陸的話,能夠將他們的一級域名設置爲相同的,如主站點設置爲eoitek.test,子站點設置爲sharplook.eoitek.test。在建立cookie的時候,經過設置domain=.eoitek.test;path=/;便可實現兩個域名之間的cookie共享,若是將認證信息的token放在cookie中則能夠實現單點登陸了。

//eoitek.test站點

import cookies from 'cookiesjs';
export default {
  name: 'agent',
  mounted() {
    cookies({'fullname': null, 'company': null});
    if (!cookies('fullname')) {
      cookies({fullname: 'binbin', company: 'eoitek'}, 
      {expires: 100 * 24 * 3600,
       domain: '.eoitek.test', path: '/'});
    }
   }
}

clipboard.png

clipboard.png

能夠看出在兩個站點中都能訪問到咱們設置的兩個cookie,這樣實現了跨域訪問cookie和單點登陸。

相關文章
相關標籤/搜索