跨域設(shè)置Cookie失效問(wèn)題解決方案原理分析
問(wèn)題出現(xiàn)場(chǎng)景
在做登錄功能時(shí),想把用戶的信息通過(guò)Set-cookie在客戶端設(shè)置cookie信息。
1.服務(wù)端通過(guò)cors中間件實(shí)現(xiàn)接口跨域訪問(wèn)、koa-session-minimal實(shí)現(xiàn)cookie的設(shè)置。
代碼實(shí)現(xiàn)如下
const session = require('koa-session-minimal') const cors = require('@koa/cors'); // app.js const app = new Koa() app.use(cors()) // 存放sessionId的cookie配置, 相關(guān)的一些字段配置說(shuō)明可以查看http協(xié)議。 let cookie = { maxAge: 2 * 60 * 1000, // cookie有效時(shí)長(zhǎng) expires: new Date('2022-08-26'), // cookie失效時(shí)間 path: '/', // 寫cookie所在的路徑 domain: 'localhost', // 寫cookie所在的域名 httpOnly: false, // 是否只用于http請(qǐng)求中獲取 overwrite: false, // 是否允許重寫 // secure: '', sameSite: 'strict', // signed: '', } // 使用session中間件 app.use(session({ key: 'SESSION_ID', cookie: cookie }))
登陸接口相關(guān)代碼
// login接口 // ... if (!err) { ctx.session = { user_id: adminId, count: 0 } ctx.response.status = 200; // ... } // ...
一切進(jìn)展順利,接口響應(yīng)成功,響應(yīng)頭也有我們?cè)O(shè)置的cookie字段。但是事情的背后往往沒(méi)有這么簡(jiǎn)單,當(dāng)我去看Application中的Cookie信息時(shí),發(fā)現(xiàn)怎么都找不到我想要的SESSION_ID字段,百思不得姐。
問(wèn)題出現(xiàn)的解決方案如下
1.通過(guò)查閱一些資料后,發(fā)現(xiàn)瀏覽器的同源策略是對(duì)跨域的cookie有做一些限制的。其中Access-Control-Allow-Credentials字段就控制著對(duì)跨域cookie的設(shè)置。
Access-Control-Allow-Credentials
響應(yīng)頭用于在請(qǐng)求要求包含 credentials(Request.credentials 的值為 include
)時(shí),告知瀏覽器是否可以將對(duì)請(qǐng)求的響應(yīng)暴露給前端 JavaScript 代碼。
當(dāng)請(qǐng)求的 credentials 模式為 include
時(shí),瀏覽器僅在響應(yīng)標(biāo)頭 Access-Control-Allow-Credentials
的值為 true
的情況下將響應(yīng)暴露給前端的 JavaScript 代碼。(這段文字是來(lái)自MDN文檔)。
我理解是只有開啟后,瀏覽器在讀取到響應(yīng)頭的Set-cookie字段時(shí),才能將cookie字段設(shè)置于瀏覽器中。于是我根據(jù)cors使用文檔做出了代碼上的調(diào)整:
const app = new Koa() const koaOptions = { origin: 'http://localhost:9529', credentials: true }; app.use(cors(koaOptions))
2.于是本人胸有成竹的開啟了新一遍的流程測(cè)試,想必這次是能成功的。經(jīng)過(guò)了幾S的流程測(cè)試之后,我得到了一個(gè)結(jié)果:失敗是成功之母。
顯然我們這次又未在Application的cookie中找到我們想要的SESSION_ID字段,我再次沉浸式的翻閱了MDN的cookie相關(guān)文檔。
3.發(fā)現(xiàn)文檔中其實(shí)是有寫到:Access-Control-Allow-Credentials 標(biāo)頭需要與 XMLHttpRequest.withCredentials 或 Fetch API 的 Request() 構(gòu)造函數(shù)中的 credentials 選項(xiàng)結(jié)合使用。
Credentials 必須在前后端都被配置(即 Access-Control-Allow-Credentials header 和 XHR 或 Fetch request 中都要配置)才能使帶 credentials 的 CORS 請(qǐng)求成功。
XMLHttpRequest.withCredentials
屬性是一個(gè)布爾類型,它指示了是否該使用類似 Cookies、Authorization Headers (頭部授權(quán)) 或者 TLS 客戶端證書這一類資格證書來(lái)創(chuàng)建一個(gè)跨站點(diǎn)訪問(wèn)控制(cross-site Access-Control
)請(qǐng)求。
在同一個(gè)站點(diǎn)下使用 withCredentials
屬性是無(wú)效的。此外也會(huì)被用做響應(yīng)中
Cookies 被忽視的標(biāo)示。默認(rèn)值是 false。
如果在發(fā)送來(lái)自其他域的 XMLHttpRequest 請(qǐng)求之前,未設(shè)置withCredentials
為 true,那么就不能為它自己的域設(shè)置 Cookie 值。
而通過(guò)設(shè)置 withCredentials
為 true 獲得的第三方 Cookies,將會(huì)依舊享受同源策略,因此不能被通過(guò)document.cookie或者從頭部相應(yīng)請(qǐng)求的腳本等訪問(wèn)。(這段文字是來(lái)自MDN文檔)。
4.根據(jù)以上信息,我調(diào)整了前端項(xiàng)目封裝的request模塊代碼,將withCredentiaols設(shè)置成了true:
const service = axios.create({ baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url withCredentials: true, // send cookies when cross-domain requests timeout: 5000 // request timeout })
再一次的進(jìn)行我們的流程測(cè)試,果然功夫不負(fù)有心人,終于是在Application中看到了心心念的SESSION_ID:
反思和結(jié)語(yǔ)
踏破鐵鞋無(wú)覓處,得來(lái)全不費(fèi)工夫。我們?cè)谟鲆妴?wèn)題的時(shí)候,應(yīng)該盡量從問(wèn)題的本質(zhì)出發(fā)尋找突破口,試著從另一個(gè)角度切入。
其次就是對(duì)相關(guān)知識(shí)的掌握程度,我在這次的遇見問(wèn)題和解決問(wèn)題的過(guò)程中做出了反思,確實(shí)有尋找到突破口:瀏覽器的同源策略限制。
但是對(duì)其相關(guān)的策略掌握不夠深入,導(dǎo)致花費(fèi)了比正常多幾倍的時(shí)間去解決問(wèn)題,經(jīng)過(guò)這次的文檔查閱,我對(duì)跨域設(shè)置cookie以及瀏覽器同源限制策略,有了更進(jìn)一步的認(rèn)知。
以上就是跨域設(shè)置Cookie失效問(wèn)題解決方案原理分析的詳細(xì)內(nèi)容,更多關(guān)于跨域設(shè)置Cookie失效解決的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
JS仿照3D手辦模型展臺(tái)實(shí)現(xiàn)示例詳解
這篇文章主要為大家介紹了JS 實(shí)現(xiàn)偽3D手辦模型展臺(tái)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09微信小程序Server端環(huán)境配置詳解(SSL, Nginx HTTPS,TLS 1.2 升級(jí))
這篇文章主要介紹了微信小程序Server端環(huán)境配置詳解(SSL, Nginx HTTPS,TLS 1.2 升級(jí))的相關(guān)資料,需要的朋友可以參考下2017-01-01JavaScript知識(shí):構(gòu)造函數(shù)也是函數(shù)
構(gòu)造函數(shù)就是初始化一個(gè)實(shí)例對(duì)象,對(duì)象的prototype屬性是繼承一個(gè)實(shí)例對(duì)象。本文給大家分享javascript構(gòu)造函數(shù)詳解,對(duì)js構(gòu)造函數(shù)相關(guān)知識(shí)感興趣的朋友一起學(xué)習(xí)吧2021-08-08一文詳解webpack中l(wèi)oader與plugin的區(qū)別
這篇文章主要為大家介紹了一文詳解webpack中l(wèi)oader與plugin的區(qū)別詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02Javascript設(shè)計(jì)模式之原型模式詳細(xì)
這篇文章主要介紹了Javascript設(shè)計(jì)模式之原型模式,原型模式用于在創(chuàng)建對(duì)象時(shí),通過(guò)共享某個(gè)對(duì)象原型的屬性和方法,從而達(dá)到提高性能、降低內(nèi)存占用、代碼復(fù)用的效果。下面小編將詳細(xì)介紹 ,需要的朋友可以參考下2021-09-09JS前端設(shè)計(jì)模式之發(fā)布訂閱模式詳解
這篇文章主要為大家介紹了JS前端設(shè)計(jì)模式之發(fā)布訂閱模式詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08JavaScript編程通過(guò)Matlab質(zhì)心算法定位學(xué)習(xí)
這篇文章主要為大家介紹了JavaScript編程中通過(guò)Matlab質(zhì)心算法來(lái)定位的算法學(xué)習(xí),有需要的朋友可以借鑒參考下,希望能夠有所幫助2021-10-10