問題:我的 HTML/JavaScript 應用程式在處理重定向時收到 CORS 錯誤。
目標:將 Apache 配置為僅在特定重定向期間包含 HTTP 標頭。
重要提示:此 HTML 在瀏覽器中從本地加載的檔案運行,而不是從 Web 服務器提供的頁面運行。
編碼:
<body>
<div id="response">Loading page ...</div>
<script type="text/javascript">
async function get_response() {
let url = 'https://example.com/endpoint'
fetch(url, {
redirect: "follow"
})
.then(response => response.text())
.then(data => {
document.getElementById('response').innerHTML = data;
})
.catch(error => {
console.log(error);
});
}
get_response();
</script>
</body>
代碼說明:
上面的代碼從 URL 中獲取資料并將其顯示在瀏覽器中。但是,網站會發送 302 重定向(按設計)。重定向會導致 CORS 錯誤。
CORS 錯誤:
CORS 策略已阻止從源“null”訪問“https://example.com/endpoint”獲取:請求的資源上不存在“Access-Control-Allow-Origin”標頭。如果不透明的回應滿足您的需求,請將請求的模式設定為“no-cors”以獲取禁用 CORS 的資源。
生成重定向的 Apache 配置:
RewriteEngine on
RewriteRule ^(/endpoint)$ /system/endpoint.php? [END,NE,R=302]
不可接受的可能解決方法:
將 Apache 配置為在 RewriteRule 之前發送 CORS 標頭:
標頭始終設定 Access-Control-Allow-Origin "*"
這不是一個好的解決方案,因為我不想只為所有 URL 發送這個標頭這個重定向。其他頁面確實設定了此標頭,并且當 Chrome 接收到多個具有相同值的Access-Control-Allow-Origin標頭時,會生成錯誤而不是接受標頭。注意:需要始終設定 AFAIK 標頭以包含 3xx 回應的標頭。
- 修改應用程式以使用重定向的 URL 而不是重定向的 URL。
這將不起作用,因為最終 URL 是可配置的,并且目標是在后端路由更改時不修改應用程式。
其他解決方法:
通過撰寫這個問題并仔細思考問題,我意識到我的 RewriteRule 正在生成一個重定向,這并不是所有情況都需要的。對于同一域內的重定向,URL 重寫就足夠了。對于重定向到我需要做的子域,重寫 URL 是不夠的。
對于相同的域 URL 更改,這將起作用:
RewriteRule ^(/endpoint)$ /system/endpoint.php? [L]
對于真正的重定向,我需要一種方法來有條件地包含 CORS 標頭。
uj5u.com熱心網友回復:
解決方案是將 Apache<If>
指令與服務器變數結合起來REQUEST_URI
:
<If "%{REQUEST_URI} == '/endpoint'">
Header always set Access-Control-Allow-Origin "*"
</If>
RewriteEngine on
RewriteRule ^(/endpoint)$ https://example2.com/system/endpoint? [END,NE,R=302]
新端點還必須配置為使用Access-Control-Allow-Origin
標頭進行回應。
Apache <If> 指令
Apache 服務器變數
[更新]
通過回應Access-Control-Allow-Origin "*"
,我的解決方案違背了 CORS 的目的,即防止未經授權的資源共享。此解決方案將在安全審核中觸發警告或違規。由于我只是在后端通配特定路由而不是所有路由,因此可以對此進行解釋/記錄。
當我在 Stack Overflow 和 Internet 上研究這個問題時,每個答案/文章都建議回傳 `Access-Control-Allow-Origin "*" 標頭。這幾乎是錯誤的解決方案。安全控制的目的是強制執行,而不是繞過它。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/470865.html