# 本機開發 vs. CORS 問題 [TOC] # CORS介紹 * https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS * 為預防不同源(not same origin)存取資源或操作XHR行為,瀏覽器會在 request 的 header 中加上 origin 來表示發送者的 Domain name;後端接收 request 時會檢查 origin是否在允許清單中,若不符合條件則擋下操作,瀏覽器中的console可以看到 CORS 的錯誤。 ![](https://i.imgur.com/usFqfC7.png) # 起因 * Backend 採用更嚴格的 CORS 原則。原本 Access-Control-Allow-Origin 設置為 ```*``` (wildcard),後改為以正面列舉(白名單概念)允許通過之domain name,使 ```http://localhost:3001``` 之類的無法符合 CORS 原則而被擋下。 ![](https://i.imgur.com/CTobaxS.png) # 具體限制 * 目前後端有設置 CORS 可分為以下兩種類型 1. 通過 system-kong 的微服務,例如 iam-service 2. 未通過 system-kong 的微服務,例如 cloudstorage-service * 補充說明 -- 若使用 Postman 或 cUrl 是不會有限制的,原因是其它工具並未像瀏覽器強制在 header 中加入 origin。 # 不好的解法 * 請後端設置 http://localhost 為白名單,簡單暴力但不是正確的解法,風險很高 # 解法一 (針對kong) * 想法:將直接打給 kong 的 request 轉透過 middleware 發送 * 因此修改原先 login api: http://api.oneai.twcc.tw/iam/v1/login 並導流至 middleware 例如: `VUE_APP_IDENTITY_ENDPOINT=https://api.oneai.twcc.tw/iam/api/v1` ![](https://i.imgur.com/aSofJGb.png) * 在 nginx 中新增一個 location `/api` ,以此開頭的 request 都將 bypass 至 middleware ``` // nginx.conf http { server { listen 80; location /api { proxy_pass http://middleware-service.asus-paas-2:8888; } location / { root /usr/share/nginx/html; try_files $uri /index.html; } } } ``` 在 middleware 中進行加工,將 origin 移除 ``` delete req.headers['origin'] ``` ![](https://i.imgur.com/wiikAxp.png) # 解法二 (針對無法穿過middleware或kong) * 實際上分兩個問題: 1. cloudstorage 不建議穿過 middleware -- 理由是流量過大 3. aws-sdk 有對 req. 做 signature 驗證,localhost 或 ip 會被視為不安全的 req. * 想法:發送者必須偽裝成有domain name的方式,可透過本機啟動 nginx server 作偽裝 * 後端 CORS 設置一組無用的假 domain name 作為開發使用,在此例為 ```http://local-dev.oneai.twcc.tw``` * ``/etc/host`` 新增一組 ```127.0.0.1 local-dev.oneai.twcc.tw``` * 安裝 [nginx](http://nginx.org/en/docs/windows.html) * 設定 nginx 將流量導向本機(以vue-cli啟動的```localhost:3001```) ``` // nginx/conf/nginx.conf http { server { listen 80; location / { proxy_pass http://localhost:3001; } } } ``` * 如此一來發送出去的 request 在瀏覽器中會被加上 origin 為 ```http://local-dev.oneai.twcc.tw```,因此是合法的呼叫 API ![](https://i.imgur.com/M9LChUg.png) # NGINX指令說明 ``` start nginx start an nginx nginx -s stop fast shutdown nginx -s quit graceful shutdown nginx -s reload changing configuration, starting new worker processes with a new configuration, graceful shutdown of old worker processes ```