---
# System prepended metadata

title: 本機開發 vs. CORS 問題

---

# 本機開發 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
```