上週以為搞定了 CORS 與 Windows 驗證不相容問題,不料還有續集,接到需求 - 呼叫端來源 URL 可能有多筆,寫 IP 也要能通。

CORS 設定時需透過 Access-Control-Allow-Origin Header 指定呼叫端 URL,而 Access-Control-Allow-Origin 限定一筆;若想允許多個來源,在 ASPX 程式可以比對 Referrer 動態設定 Access-Control-Allow-Origin 為對方 URL,倒也不是難題。

BUT! 因為 IIS 停用匿名需要登入,AJAX 呼叫遇到 401 回應時就得有 Access-Control-Allow-Origin,這部分無法由程式控制,必須寫在 web.config。幸好還有一招,Access-Control-Allow-Origin 支援萬用字元「*」,用 <location path="cross-site.aspx"> 限制範圍對所有 URL 開放 CORS 存取,評估風險尚在可接受範圍。

BUT! 因為啟用的是 Windows 整合驗證,XHR 必須加上 withCredentials 才能過關,用 withCredentials 就不能用萬用字元,不然會引發 The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute. 錯誤,

上帝為你關了一扇門,同時會幫你開一扇窗,正要跳窗卻發現外面還有鐵窗;上帝微笑指了指煙囪,沿著煙囪往上爬卻發現聖誕老公公卡在洞口...

每項限制都有留活路,但我偏偏遇上冷門的 CORS + IIS Windows 驗證情境,活路一條條被堵死。

所幸,天無絕人之路,IIS 有個 IIS CORS Module,提供彈性化的 Access-Control-Allow-* 回應,能克服無法指定多個 Access-Control-Allow-Origin 的限制。

安裝後,IIS 管理員查看模組清單可看到 CorsModule 項目:

如果你只是要針對多個來源開放 CORS,這樣設定就可以:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <cors enabled="true" failUnlistedOrigins="true">
            <add origin="http://192.168.1.1" allowCredentials="true" />
            <add origin="http://172.28.1.1" allowCredentials="true" />
            <add origin="http://web.whatever.net" allowCredentials="true" />
        </cors>
    </system.webServer>
</configuration>

若要更嚴謹,可以用 location 限縮開放對象:

<configuration>
    <location path="cross-site.aspx">
        <system.webServer>
            <cors enabled="true" failUnlistedOrigins="true">
                <!-- 略 -->
            </cors>
        </system.webServer>
    </location>
</configuration>

CORS Module 還有許多細部設定,例如:allowHeaders、allowMethods... 等等,詳細用法可參考官方文件

又過一關。

Tips of how to set multiple Access-Control-Allow-Origin in IIS with CORS Module.


Comments

Be the first to post a comment

Post a comment