1. 程式人生 > >跨域訪問CORS

跨域訪問CORS

上次研究了一下利用Heroku app寫了一個webservice,供Salesforce Lightning fetch通過apex呼叫,後來由於只是讀取資料,所以提出要改成直接在js裡呼叫webserivce, 不通過Apex, 這裡就涉及到一個跨域訪問的問題。

 

對大佬而言這麼簡單的問題我研究了3天,簡直蝸牛了,不過還好最終搗鼓通了。

起初試了很多方法遇到了一個Preflight Request,翻譯過來叫什麼預起飛請求, 說的是相對於普通的請求,“預起飛”請求需要在實際請求(比如POST)的同時,瀏覽器會先向伺服器傳送一個OPTION請求用來驗證請求資料對訪問資料是否安全,確認安全後實際的請求才會被髮出並處理。因此我遇到一個錯誤,伺服器端log顯示, OPTION 請求返回200, ok, 但是實際POST請求卻總是報錯 “unexpected token o in json at position express” ,  這種情況下,一種解決方法說可以安裝 cors 包來解決(cors 包會自動處理OPTIONS請求), 但是我試了很多次都不好使,放棄了; 還有種方式就是改變Content-Type 型別由 “Application/json” 變成 “text/plain”, 使得請求轉變成普通型別,避免預起飛(Preflight),這種方式成功了。

https://dev.to/effingkay/cors-preflighted-requests--options-method-3024

 

 

然而之後又產生了一個新的錯誤說"Refused to connect to because it violates the following Content Security Policy directive: "connect-src 'self' example1.com example2.com", 查其原因是因為Content Security Policy 中connectSrc directive配置了允許訪問的源,這裡我用了 helmet-csp package。

https://helmetjs.github.io/docs/csp/

var csp = require('helmet-csp');
app.use(csp({
  directives: {
    defaultSrc: ["'self'"],
    scriptSrc: ["'self'", "'unsafe-inline'"],
    reportUri: '/report-violation',
    connectSrc:[ "'self'"],
    objectSrc: ["'none'"],
    upgradeInsecureRequests: true,
    workerSrc: false  
  },
  reportOnly: true
}));

 

 

然而之後又產生了一個新的錯誤說是“Access to fetch at  from origin has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.” 查明原因是因為,瀏覽器並不知道其訪問的內容是否安全,CORS策略中有個Header Access-Control-Allow-Origin, 伺服器端需要在響應中新增此Header以告知瀏覽器該返回響應中的資料對於瀏覽器當前域是允許的,否則瀏覽器會阻止訪問。

https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin

app.use(function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*"); // update to match the domain you will make the request from
  res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
  next();
});

 

最終調通了