> 需求描述:理解cookie
維持登陸態的幾種方式:
傳統身份驗證的方法
HTTP 是一種沒有狀態的協議,也就是它並不知道是誰是訪問應用。這裏咱們把用戶當作是客戶端,客戶端使用用戶名還有密碼經過了身份驗證,不過下回這個客戶端再發送請求時候,還得再驗證一下。
解決的方法就是,當用戶請求登陸的時候,若是沒有問題,咱們在服務端生成一條記錄,這個記錄裏能夠說明一下登陸的用戶是誰,而後把這條記錄的 ID 號發送給客戶端,客戶端收到之後把這個 ID 號存儲在 Cookie 裏,下次這個用戶再向服務端發送請求的時候,能夠帶着這個 Cookie ,這樣服務端會驗證一個這個 Cookie 裏的信息,看看能不能在服務端這裏找到對應的記錄,若是能夠,說明用戶已經經過了身份驗證,就把用戶請求的數據返回給客戶端。
上面說的就是 Session,咱們須要在服務端存儲爲登陸的用戶生成的 Session ,這些 Session 可能會存儲在內存,磁盤,或者數據庫裏。咱們可能須要在服務端按期的去清理過時的 Session 。
基於 Token 的身份驗證方法
使用基於 Token 的身份驗證方法,在服務端不須要存儲用戶的登陸記錄。大概的流程是這樣的:
一、客戶端使用用戶名跟密碼請求登陸
二、服務端收到請求,去驗證用戶名與密碼
三、驗證成功後,服務端會簽發一個 Token,再把這個 Token 發送給客戶端
四、客戶端收到 Token 之後能夠把它存儲起來,好比放在 Cookie 裏或者 Local Storage 裏
五、客戶端每次向服務端請求資源的時候須要帶着服務端簽發的 Token
六、服務端收到請求,而後去驗證客戶端請求裏面帶着的 Token,若是驗證成功,就向客戶端返回請求的數據
Cookie
Cookie種類
一、臨時Cookie(會話Cookie)
二、永久Cookie
cookie分爲兩種,一種是硬盤上的,另外一種是內存上的,一個網站一般有一個.txt文件來存Cookies,一個Cookie對象最終轉換爲txt文件中的一條記錄。保存在瀏覽器線程分配的內存中的Cookie對象,在關閉這個瀏覽器窗口後,就銷燬了。致使種類不一樣是過時時間的設置與否決定的,若是設置了過時時間,那麼就會在過時時間未到前一直生效,請求會被攜帶,除非服務端設置了max-age強制使其失效;而沒有設置過時時間,cookie的生命週期只存在於瀏覽器會話期間,關閉窗口,cookie即消失。
Cookie被攜帶的條件
同一域名下,存在cookie,瀏覽器會默認自動發送Cookie給對應的服務器。
普通的ajax(json)請求和jsop跨域請求是默認攜帶cookie的,而cors跨域請求和fetch請求默認是不攜帶cookie的。所以,當咱們的請求須要攜帶cookie時,咱們就要對cors跨域請求和fetch請求這兩中請求方式進行特殊配置處理。
一般咱們使用的axios庫,也是對XMLHttpRequest這個對象的封裝,和ajax請求無異,由於加入了promise,解決了回調的問題。
而fetch請求若是想攜帶cookie,須要設置header裏面的參數,加上credientials: ‘include’;
CORS的方式想要攜帶cookie,須要設置以下設置
// aixos爲例const service = axios.create({baseURL: process.env.BASE_API, // node環境的不一樣,對應不一樣的baseURLtimeout: 30000, // 請求的超時時間withCredentials: true // 容許攜帶cookie})複製代碼
設置Cookie的方式
一、後端設置set-cookie,這種狀況下,前端什麼也不須要作。至關於服務器端給瀏覽器發送指令,瀏覽器自動注入cookie;,每次請求都攜帶cookie信息;
二、前端收到後端返回的信息,設置cookie;
function setDomainCookie(name, value, expiresDays = 60, host) {let date = new Date();date.setTime(date.getTime() + expiresDays * 24 * 3600 * 1000);const expires = `expires=${date.toGMTString()};`;host? '': (host = window.location.hostname.split('.').slice(-2).join('.'));const domain = `domain=${host};`;window.document.cookie = `${name}=${value};${expires}${domain}path=/`;}複製代碼
分析 && 總結
一、cookie信息自動被請求攜帶,不限於請求後端數據的請求,即便是刷新頁面,圖片,css,js,也都會攜帶本地的cookie信息,這無疑至關於浪費了請求頭的資源;
二、cookie是不容許跨域傳輸的,因此在本地localhost發送的請求是不會被攜帶到請求頭裏的,這樣就會有問題,若是不少請求都須要驗證權限,而開發環境又沒法攜帶cookie信息,就會帶來聯調上的困難;
三、cookie中可以存儲的數據有限,不一樣的瀏覽器限制大小不同。
綜上,在實現自動登陸時,前端收到服務端返回的token,能夠存到localstorage裏,而後塞入請求頭中,全部對於數據的請求都會攜帶此頭部字段,雖然localstorage沒有過時這一律念,咱們能夠本身手動設置,每次發送請求前都判斷一遍是否過時,以下:
// 存入if (cacheParams.cacheTime < 0) cacheParams.cacheTime = 3600000;var result = { data: response.data, expiration: new Date().getTime() + cacheParams.cacheTime };localStorage.setItem(cacheParams.cacheName, JSON.stringify(result));// 取出判斷const data = JSON.parse(data);if (parseInt(data.expiration) - new Date().getTime() <= 3000) {// 說明已過時,作相應處理}複製代碼
設置請求頭:
// 以axios實例爲例netApi.interceptors.request.use((request) => {removePending(request); // 在一個ajax發送前執行一下取消操做config.cancelToken = new APICancelToken((c) => {// 這裏的ajax標識我是用請求地址&請求方式拼接的字符串,固然你能夠選擇其餘的一些方式pending.push({ u: `${request.url}&${request.method}`, f: c });});if (readLocalStorage('X-Token')) {request.headers.token = readLocalStorage('X-Token'); // 攜帶token}return request;}, error => Promise.reject(error));複製代碼
題外記,若是存有登陸信息的cookie文件,被複制到另外一臺設備的指定目錄下,去訪問這個cookie對應的網站,是否是也能正常訪問呢?
個人理解是能夠的,或者換一種方式,個人設備上的cookie信息被劫持了,而後被用來登陸我使用的網站了,是否是意味着這我的在行駛着個人權力,理論上是,但是如今的安全防範策略那麼多,可以存到cookie裏的信息未必是最重要的明文信息,因此即便被劫持了也影響不大。
歡迎指正!
參考文章:
一、[React16新的生命週期函數getDerivedStateFromProps的使用,你也許並不須要派生狀態【譯】](https://blog.csdn.net/nnxxyy1111/article/details/80832525)
二、[HTTP--Request Headers及Cookies](https://www.cnblogs.com/wxinyu/p/8005621.html)
三、[狀態保持中的Cookie與Session](https://blog.csdn.net/sundacheng1989/article/details/8194466)
四、[CORS簡介](https://www.cnblogs.com/loveis715/p/4592246.html)
五、[axios的cookie跨域以及相關配置
](https://segmentfault.com/a/1190000011811117?utm_source=tag-newest)