2020/08/08

跨來源資源共用CORS處理方式(一)

 

寫對外公開 WebAPI 時,會因為瀏覽器安全性的關係而禁止非同源存取。

如以下範例:


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>
  <head>
    <title></title>
    <script type="text/javascript" src="js/base64.js"></script>
    <script type="text/javascript" src="js/json-min.js"></script>
    <script type="text/javascript" src="js/serverfunctionexecutor.js"></script>
    <script type="text/javascript" src="js/connection.js"></script>
  </head>

  <body>
   <form onsubmit="event.preventDefault();myFunction()">Enter name: <input type="TEXT"> Enter password: <input type="PASSWORD">
    <input type="submit" value="Login">

</form>
    <script>
      "use strict"
      function myFunction() {
        var request = getXmlHttpObject()
        request.open("GET", "http://localhost:8080/datasnap/rest/TServerMethods1/EchoString/A B C", true);
        request.onreadystatechange = function() {
          if (request.readyState == 4)
          {
            var JSONResult = parseHTTPResponse(request)
            console.log(JSONResult.result[0])
          }
        }
        request.setRequestHeader("Accept", "application/json");
        request.setRequestHeader("Content-Type", "text/plain;charset=UTF-8");
        request.setRequestHeader("If-Modified-Since", "Mon, 1 Oct 1990 05:00:00 GMT");
        request.send();
      }
    </script>
  </body>
</html>
在這裡模擬 XMLHttpRequest 對公開 WebAPI 進行登入,接著瀏覽器很不客氣的回應了:

 

再看看網路頁籤是如何發送 XHR 的訊息:

MDN網站是這麼解釋的:

跨來源資源共用標準的運作方式是藉由加入新的 HTTP 標頭讓伺服器能夠描述來源資訊以提供予瀏覽器讀取。另外,針對會造成副作用的 HTTP 請求方法(特別是 GET 以外的 HTTP 方法,或搭配某些 MIME typesPOST 方法),規範要求瀏覽器必須要請求傳送「預檢(preflight)」請求,以 HTTP 的 OPTIONS 方法之請求從伺服器取得其支援的方法。當伺服器許可後,再傳送 HTTP 請求方法送出實際的請求。伺服器也可以通知客戶端是否要連同安全性資料(包括 Cookies 和 HTTP 認證(Authentication)資料)一併隨請求送出。

於是要在後端讓 WebAPI 修正到能接受 OPTIONS 請求。

第二次發送,成功了……沒有,但回傳另一個錯誤訊息:

缺少 Access-Control-Allow-Origin 檔頭,原來如此,這檔頭又要表示什麼呢?MDN 是這麼解釋的:

Origin 標頭與 Access-Control-Allow-Origin 標頭中可以看到存取控制協定最簡單的用途。這個例子中,伺服器回傳 Access-Control-Allow-Origin: * 表示允許任何網域跨站存取資源,倘若 http://bar.other 的資源擁有者只准許來自 http://foo.example 的存取資源請求,那麼將會回傳:

Access-Control-Allow-Origin: http://foo.example

如此一來,來源並非 http://foo.example 網域(由第 10 行請求標頭中的 ORIGIN 標頭確認)便無法以跨站的方式存取資源。Access-Control-Allow-Origin 標頭必須包含請求當中的 Origin 標頭值。

這裡的來源指的是 Server 允許來自何處的 Client,以這個例子來說:

  • localhost:8080 = Server
  • localhost:9000 = Client

所以要允許的是 localhost:9000 的存取,當然,使用【*】也是可以的。

Server 端是如何編寫 CORS 配置?

敬請期待下回,或是搶先看這裡

See Also

沒有留言:

張貼留言