# [瀏覽器] 公司專案無法從 local 環境登入的問題 ###### tags: `前端筆記` `瀏覽器` `Cookie` ## 問題說明 使用 local 啟動 OMS 專案時都無法使用 Chrome 瀏覽器登入,查看原因發現是每次請求都沒帶 `cookies`,所以即便登入成功後,進入首頁後再次訪問相關 API 後都會被認作未登入(因為請求沒帶登入後從後端拿的 `cookies`)。 ### 使用測試站登入 ![](https://hackmd.io/_uploads/HJvsgncg6.png) (登入成功後確實有在 `response header` 內取得 `Set-Cookie`) ![](https://hackmd.io/_uploads/r1Pjg29la.png) (訪問請求有在 `request header` 帶入 `Cookie` 供後端確認身份) ### 使用 local 登入 ![](https://hackmd.io/_uploads/SJ22-nqgT.png) (確實有登入成功 + `response header` 內取得 `Set-Cookie`) ![](https://hackmd.io/_uploads/S1n3-29lT.png) (但是在接下來的訪問請求就沒有在 `request header` 中帶入 `Cookie`) ![](https://hackmd.io/_uploads/B1n3-29eT.png) (後端自然也無法判斷訪問者身份) ## 問題排查 ### 錯誤的方向 1. 不是專案 webpack 設定問題 2. 不是 node 版本相關問題 ### 為什麼只有 Chrome 不行? > Chrome 預計在 2 月推出 80 版,屆時尚未聲明 SameSite 值的 Cookie 就會被視為 `SameSite=Lax` Cookie。只有設有 `SameSite=None`; Secure 的 Cookie 可供外部資源透過安全連線進行存取。[`SameSite=None`](https://chromestatus.com/feature/5088147346030592) 和 [Secure](https://chromestatus.com/feature/5633521622188032) 的 Chrome Platform Status 追蹤工具會持續更新,提供最新版本的發布資訊。 > *[ref. 準備好迎接全新的 Cookie 設定:SameSite=None; Secure ](https://developers.google.com/search/blog/2020/01/get-ready-for-new-samesitenone-secure?hl=zh-tw)* 因為在 2020/02 月開始 Chrome 規範當發起訪問者及被訪問者的來源不同時(也就是 Cookie 同源政策 - Cookie Same Origin Policy),瀏覽器不會在訪問請求中帶入 `Cookie`: ![](https://miro.medium.com/v2/resize:fit:720/format:webp/1*aJZwQc2u5QA6jN4d-VHWvg.png) (Cookie 的同源政策 (Same Origin Policy) 示意圖 - *[ref. 網站安全🔒 再探同源政策,談 SameSite 設定對 Cookie 的影響與注意事項](https://medium.com/%E7%A8%8B%E5%BC%8F%E7%8C%BF%E5%90%83%E9%A6%99%E8%95%89/%E5%86%8D%E6%8E%A2%E5%90%8C%E6%BA%90%E6%94%BF%E7%AD%96-%E8%AB%87-samesite-%E8%A8%AD%E5%AE%9A%E5%B0%8D-cookie-%E7%9A%84%E5%BD%B1%E9%9F%BF%E8%88%87%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A0%85-6195d10d4441)*) #### 所以什麼是同源? 1. 只要訪問者及被訪問者的 `Domain` 跟 `Path` 與 `Cookie` 一致,就會被認作同源,所以在發起請求時 `Cookie` 就會被送出 ![](https://hackmd.io/_uploads/SyDcP2cgT.png) (可以發現 `Cookie` 的 `Domain`: `api-oms.boxeexuat.info`, `Path`: `/`,而當前訪問者的網址為 `https://oms.boxeexuat.info/#/dashboard`,所以發起的訪問會帶 `Cookie`) 2. 如果 `Cookie` 中有設定 `secure` 這個屬性,那麼瀏覽器還會額外多判斷 Scheme 是不是`https`,是的話才會送出 `Cookie` #### 因為不符合 Cookie 同源政策,所以無法在 local 端發送訪問時帶入 `Cookie` 因為使用 chrome local 發起訪問時,當前的網址就會是 `http://127.0.0.1:8888/#/login`,與被訪問者的 `Domain` 明顯不同,所以自然無法帶入 `Cookie`。 ![](https://hackmd.io/_uploads/HkP9j39e6.png) ### 那為什麼 Firefox 可以? 因為目前 Firefox 尚未跟上 Chrome 的腳步,所以沒有 Cookie 同源政策。 ## 除了瀏覽器的把關,前端還需要做什麼設定嗎? 要的,以使用 `axios` 發出請求為例,必須多設定 `withCredentials: true`: ```javascript= // ref.[Make Axios send cookies in its requests automatically](https://stackoverflow.com/questions/43002444/make-axios-send-cookies-in-its-requests-automatically) // 每次都帶入 axios.get(BASE_URL + '/todos', { withCredentials: true }); // 每個訪問都帶入 axios.defaults.withCredentials = true // 用實例的方式處理 const instance = axios.create({ withCredentials: true, baseURL: BASE_URL }) instance.get('/todos') ``` 接下來前端就沒有什麼事情了... ## 後端需要協助的部份 處理基本的同源設定的 `respone header` 外(`Access-Control-Allow-Origin`, `Access-Control-Allow-Methods` 以及 `Access-Control-Allow-Headers`),還需要 `Access-Control-Allow-Credentials: true` 才可以讓 `response header` 中設定的 `Set-Cookie` 起到效果(這樣子 `request header` 才會帶入 `Cookie`)。 另外 `Set-Cookie` 還需要多設定成: ```javascript= // SameSite=None; Secure -> cookie 在不同來源訪問時帶入,只有這個辦法才可以確保 https + 不同來源訪問時會帶入 Cookie Set-Cookie: <cookie-name>=<cookie-value>; SameSite=None; Secure ``` ## 除了 `SameSite=None; Secure` 外,還可以怎麼設定? :::info 共有三種:`SameSite=None; Secure`, `SameSite=Lax`, `SameSite=Strict`。 ::: 1. `SameSite=Strict` 最嚴格的模式: > Means that the browser sends the cookie only for same-site requests, that is, requests originating from the same site that set the cookie. If a request originates from a different domain or scheme (even with the same domain), no cookies with the `SameSite=Strict` attribute are sent. 訪問與結果必須是相同的 domain 以及相同的 scheme 時,瀏覽器才會帶入 `Cookie`。 2. `SameSite=Lax` 較為寬鬆的模式: > Means that the cookie is not sent on cross-site requests, such as on requests to load images or frames, but is sent when a user is navigating to the origin site from an external site (for example, when following a link). This is the default behavior if the `SameSite` attribute is not specified. 1. `Cookie` 無法在不同的網址的訪問中帶入 2. 不過接受訪問者「有限度地」帶入 `Cookie` 3. 如果沒有特別設定 `SameSite` 的屬性為何,那麼 `SameSite=Lax` 就是預設值 ![](https://hackmd.io/_uploads/Hy2gew6e6.png) (基本上只有使用 `<a></a>` 比較常用,*[ref. Cookie 的 SameSite 属性](https://www.ruanyifeng.com/blog/2019/09/cookie-samesite.html)*) ## Recap 1. 目前在 Chrome 中,cookie 的來源必須與訪問方同源,才可以在訪問攜帶 cookie(這也是為什麼在本地開發時無法登入,但是在測試及正式站可以登入) 2. 基本上這部分需要後端協助多設定 `response header` ## 參考資料 1. [Set-Cookie](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie) 2. [CORS 跨域 AJAX 與 Cookie 請求](https://scar.tw/article/2019/01/22/cors-ajax-and-cookie-request/) 3. [網站安全🔒 再探同源政策,談 SameSite 設定對 Cookie 的影響與注意事項](https://medium.com/%E7%A8%8B%E5%BC%8F%E7%8C%BF%E5%90%83%E9%A6%99%E8%95%89/%E5%86%8D%E6%8E%A2%E5%90%8C%E6%BA%90%E6%94%BF%E7%AD%96-%E8%AB%87-samesite-%E8%A8%AD%E5%AE%9A%E5%B0%8D-cookie-%E7%9A%84%E5%BD%B1%E9%9F%BF%E8%88%87%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A0%85-6195d10d4441) 4. [零基礎資安系列(三)-網站安全三本柱(Secure & SameSite & HttpOnly)](https://tech-blog.cymetrics.io/posts/jo/zerobased-secure-samesite-httponly/)