首頁 > 軟體

跨域設定Cookie失效問題解決方案原理分析

2022-08-29 22:04:49

問題出現場景

在做登入功能時,想把使用者的資訊通過Set-cookie在使用者端設定cookie資訊。

1.伺服器端通過cors中介軟體實現介面跨域存取、koa-session-minimal實現cookie的設定。

程式碼實現如下

  const session = require('koa-session-minimal')
  const cors = require('@koa/cors');
  // app.js
  const app = new Koa()
  app.use(cors())
  // 存放sessionId的cookie設定, 相關的一些欄位設定說明可以檢視http協定。
  let cookie = {
    maxAge: 2 * 60 * 1000, // cookie有效時長
    expires: new Date('2022-08-26'),  // cookie失效時間
    path: '/', // 寫cookie所在的路徑
    domain: 'localhost', // 寫cookie所在的域名
    httpOnly: false, // 是否只用於http請求中獲取
    overwrite: false,  // 是否允許重寫
    // secure: '',
    sameSite: 'strict',
    // signed: '',
  }
  // 使用session中介軟體
  app.use(session({
    key: 'SESSION_ID',
    cookie: cookie
  }))

登陸介面相關程式碼

  // login介面
  // ...
  if (!err) {
    ctx.session = {
      user_id: adminId,
      count: 0
    }
    ctx.response.status = 200;
    // ...
  }
  // ...

一切進展順利,介面響應成功,響應頭也有我們設定的cookie欄位。但是事情的背後往往沒有這麼簡單,當我去看Application中的Cookie資訊時,發現怎麼都找不到我想要的SESSION_ID欄位,百思不得姐。

問題出現的解決方案如下

1.通過查閱一些資料後,發現瀏覽器的同源策略是對跨域的cookie有做一些限制的。其中Access-Control-Allow-Credentials欄位就控制著對跨域cookie的設定。

Access-Control-Allow-Credentials 響應頭用於在請求要求包含 credentials(Request.credentials 的值為 include)時,告知瀏覽器是否可以將對請求的響應暴露給前端 JavaScript 程式碼。

當請求的 credentials 模式為 include 時,瀏覽器僅在響應檔頭 Access-Control-Allow-Credentials 的值為 true 的情況下將響應暴露給前端的 JavaScript 程式碼。(這段文字是來自MDN檔案)。

我理解是隻有開啟後,瀏覽器在讀取到響應頭的Set-cookie欄位時,才能將cookie欄位設定於瀏覽器中。於是我根據cors使用檔案做出了程式碼上的調整:

    const app = new Koa()
    const koaOptions = {
      origin: 'http://localhost:9529',
      credentials: true
    };
    app.use(cors(koaOptions))

2.於是本人胸有成竹的開啟了新一遍的流程測試,想必這次是能成功的。經過了幾S的流程測試之後,我得到了一個結果:失敗是成功之母。

顯然我們這次又未在Application的cookie中找到我們想要的SESSION_ID欄位,我再次沉浸式的翻閱了MDN的cookie相關檔案。

3.發現檔案中其實是有寫到:Access-Control-Allow-Credentials 檔頭需要與 XMLHttpRequest.withCredentials 或 Fetch API 的 Request() 建構函式中的 credentials 選項結合使用。

Credentials 必須在前後端都被設定(即 Access-Control-Allow-Credentials header 和 XHR 或 Fetch request 中都要設定)才能使帶 credentials 的 CORS 請求成功。

XMLHttpRequest.withCredentials 屬性是一個布林型別,它指示了是否該使用類似 Cookies、Authorization Headers (頭部授權) 或者 TLS 使用者端證書這一類資格證書來建立一個跨站點存取控制(cross-site Access-Control)請求。

在同一個站點下使用 withCredentials 屬性是無效的。此外也會被用做響應中 Cookies 被忽視的標示。預設值是 false。

如果在傳送來自其他域的 XMLHttpRequest 請求之前,未設定withCredentials 為 true,那麼就不能為它自己的域設定 Cookie 值。

而通過設定 withCredentials 為 true 獲得的第三方 Cookies,將會依舊享受同源策略,因此不能被通過document.cookie或者從頭部相應請求的指令碼等存取。(這段文字是來自MDN檔案)。

4.根據以上資訊,我調整了前端專案封裝的request模組程式碼,將withCredentiaols設定成了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
    })

再一次的進行我們的流程測試,果然功夫不負有心人,終於是在Application中看到了心心念的SESSION_ID:

反思和結語

踏破鐵鞋無覓處,得來全不費工夫。我們在遇見問題的時候,應該儘量從問題的本質出發尋找突破口,試著從另一個角度切入。

其次就是對相關知識的掌握程度,我在這次的遇見問題和解決問題的過程中做出了反思,確實有尋找到突破口:瀏覽器的同源策略限制。

但是對其相關的策略掌握不夠深入,導致花費了比正常多幾倍的時間去解決問題,經過這次的檔案查閱,我對跨域設定cookie以及瀏覽器同源限制策略,有了更進一步的認知。

以上就是跨域設定Cookie失效問題解決方案原理分析的詳細內容,更多關於跨域設定Cookie失效解決的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com