在重定向中包含 Header
Include Header with Redirect
问题:我的 HTML/JavaScript 应用在处理重定向时收到 CORS 错误。
Objective: 配置 Apache 以仅在特定重定向期间包含 HTTP header。
重要说明:此 HTML 在浏览器中从本地加载的文件运行,而不是从网络服务器提供的页面运行。
代码:
<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 错误:
Access to fetch at 'https://example.com/endpoint' from origin 'null'
has been blocked by CORS policy: No 'Access-Control-Allow-Origin'
header is present on the requested resource. If an opaque response
serves your needs, set the request's mode to 'no-cors' to fetch the
resource with CORS disabled.
生成重定向的 Apache 配置:
RewriteEngine on
RewriteRule ^(/endpoint)$ /system/endpoint.php? [END,NE,R=302]
不可接受的可能解决方法:
配置 Apache 在 RewriteRule 之前发送 CORS header:
Header 总是设置 Access-Control-Allow-Origin "*"
这不是一个好的解决方案,因为我不想为所有 URL 发送这个 header 只有这个重定向。其他页面确实设置了这个 header 并且当 Chrome 收到多个具有相同值的 Access-Control-Allow-Origin header 时,会生成一个错误接受 headers。注意:AFAIK header 始终设置 需要包含 header 以进行 3xx 响应。
- 修改应用程序以使用重定向的 URL 而不是重定向的 URL。
这将不起作用,因为最终 URL 是可配置的,而 objective 是在后端路由更改时不修改应用程序。
其他解决方法:
通过写这个问题并思考这个问题,我意识到我的 RewriteRule 正在生成一个并非在所有情况下都必需的重定向。对于同一域内的重定向,URL 重写就足够了。为了重定向到我需要做的子域,重写 URL 是不够的。
对于相同的域 URL 更改,这将起作用:
RewriteRule ^(/endpoint)$ /system/endpoint.php? [L]
对于真正的重定向,我需要一种方法来有条件地包含 CORS header。
解决方案是将 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
header。
[更新]
通过使用 Access-Control-Allow-Origin "*"
响应,我的解决方案违背了 CORS 防止未经授权的资源共享的目的。此解决方案将在安全审计中触发警告或违规。因为我只是在后端通配特定路由而不是所有路由,所以这可以是 explained/documented.
当我在 Stack Overflow 和 Internet 上研究这个问题时,每个 answer/article 都建议返回 `Access-Control-Allow-Origin "*" header。这几乎是错误的解决方案。安全控制的目的是强制执行,而不是绕过它。
问题:我的 HTML/JavaScript 应用在处理重定向时收到 CORS 错误。
Objective: 配置 Apache 以仅在特定重定向期间包含 HTTP header。
重要说明:此 HTML 在浏览器中从本地加载的文件运行,而不是从网络服务器提供的页面运行。
代码:
<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 错误:
Access to fetch at 'https://example.com/endpoint' from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
生成重定向的 Apache 配置:
RewriteEngine on
RewriteRule ^(/endpoint)$ /system/endpoint.php? [END,NE,R=302]
不可接受的可能解决方法:
配置 Apache 在 RewriteRule 之前发送 CORS header:
Header 总是设置 Access-Control-Allow-Origin "*"
这不是一个好的解决方案,因为我不想为所有 URL 发送这个 header 只有这个重定向。其他页面确实设置了这个 header 并且当 Chrome 收到多个具有相同值的 Access-Control-Allow-Origin header 时,会生成一个错误接受 headers。注意:AFAIK header 始终设置 需要包含 header 以进行 3xx 响应。
- 修改应用程序以使用重定向的 URL 而不是重定向的 URL。
这将不起作用,因为最终 URL 是可配置的,而 objective 是在后端路由更改时不修改应用程序。
其他解决方法:
通过写这个问题并思考这个问题,我意识到我的 RewriteRule 正在生成一个并非在所有情况下都必需的重定向。对于同一域内的重定向,URL 重写就足够了。为了重定向到我需要做的子域,重写 URL 是不够的。
对于相同的域 URL 更改,这将起作用:
RewriteRule ^(/endpoint)$ /system/endpoint.php? [L]
对于真正的重定向,我需要一种方法来有条件地包含 CORS header。
解决方案是将 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
header。
[更新]
通过使用 Access-Control-Allow-Origin "*"
响应,我的解决方案违背了 CORS 防止未经授权的资源共享的目的。此解决方案将在安全审计中触发警告或违规。因为我只是在后端通配特定路由而不是所有路由,所以这可以是 explained/documented.
当我在 Stack Overflow 和 Internet 上研究这个问题时,每个 answer/article 都建议返回 `Access-Control-Allow-Origin "*" header。这几乎是错误的解决方案。安全控制的目的是强制执行,而不是绕过它。