重定向包括标题
问题:我的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错误:
访问'https://example.com/Endpoint'来自原始'null'的获取 CORS政策已阻止:没有“访问控制 - 允许孔” 标题存在于请求的资源上。如果不透明的反应 满足您的需求,将请求的模式设置为“无现体”以获取 禁用CORS的资源。
生成重定向的Apache配置:
RewriteEngine on
RewriteRule ^(/endpoint)$ /system/endpoint.php? [END,NE,R=302]
可能无法接受的解决方法:
配置Apache在重写之前发送CORS标头:
标题始终设置访问控制-Allow-Origin“*”
这不是一个好的解决方案,因为我不想将此标头发送给所有URL,仅此一个重定向。其他页面确实设置了此标头,并且当Chrome接收到具有相同值的几个访问控制标题时,会生成错误而不是接受标题。注意:AFAIK 标题总是设置必须包括3xx响应的标头。
- 修改应用程序以使用重定向的URL而不是重定向的URL。
由于最终URL是可配置的,这将无法使用,并且目的是在后端路由更改时不要修改应用程序。
其他解决方法:
我通过编写这个问题并通过问题思考来意识到,我的重写正在生成一个对所有情况所必需的重定向。对于在同一域中的重定向,URL重写就足够了。为了重定向到我需要做的子域,重写URL是不够的。
对于相同的域URL更改,这将有效:
RewriteRule ^(/endpoint)$ /system/endpoint.php? [L]
对于真正的重定向,我需要一种有条件地包含CORS标头的方法。
Problem: My HTML/JavaScript app receives a CORS error processing a redirect.
Objective: Configure Apache to include an HTTP header only during a specific redirect.
Important note: This HTML runs in a browser from a locally loaded file and not from a page served by a web server.
The Code:
<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>
Code Description:
The above code fetches data from a URL and displays it in the browser. However, the website sends a 302 redirect (by design). The redirect causes a CORS error.
CORS Error:
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.
The Apache configuration that generates the redirect:
RewriteEngine on
RewriteRule ^(/endpoint)$ /system/endpoint.php? [END,NE,R=302]
Possible workarounds that are not acceptable:
Configure Apache to send a CORS header before the RewriteRule:
Header always set Access-Control-Allow-Origin "*"
This is not a good solution because I do not want to send this header for all URLs only this one redirect. Other pages do set this header and when Chrome receives several Access-Control-Allow-Origin headers with the same value, an error is generated instead of accepting the headers. Note: AFAIK header always set is required to include the header for 3xx responses.
- Modify the application to use the redirected URL instead of a URL that redirects.
This will not work as the final URL is configurable and the objective is to not modify the application when the backend routes change.
Other Workarounds:
I realized by writing this question and thinking through the problem, that my RewriteRule is generating a redirect that is not necessary for all situations. For a redirect within the same domain, a URL rewrite is enough. For redirecting to subdomains, which I need to do, rewriting the URL is not enough.
For the same domain URL change, this will work:
RewriteRule ^(/endpoint)$ /system/endpoint.php? [L]
For a true redirect, I need a method to conditionally include the CORS header.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
该解决方案是将Apache
&lt; IF组合使用服务器变量
request_uri
:还必须配置新的端点以用
access> access-control--允许原素
标头。<指令
apache Server变量
用
访问control-allow-origin“*”
响应,我的解决方案击败了CORS的目的,该目的是防止未经授权的资源共享。该解决方案将在安全审核中触发警告或违规行为。由于我只是在后端中的特定路线,而不是所有路线,因此可以对此进行解释/记录。当我在堆栈溢出和Internet上研究此问题时,每个答案/文章都建议返回“访问控制 - 允许 - 原始”“*”标头。那几乎是时间的错误解决方案。安全控制的目的是执行它,而不是绕过它。
The solution is to combine the Apache
<If>
directive with the server variableREQUEST_URI
:The new endpoint must also be configured to respond with the
Access-Control-Allow-Origin
header.Apache <If> Directive
Apache Server Variables
[Update]
By responding with
Access-Control-Allow-Origin "*"
, my solution defeats the purpose of CORS which is to prevent unauthorized resource sharing. This solution will trigger a warning or a violation in a security audit. Since I am only wildcarding specific routes in the backend and not all routes, this can be explained/documented.When I researched this issue on Stack Overflow and on the Internet, each answer/article recommended returning the `Access-Control-Allow-Origin "*" header. That is the wrong solution almost of the time. The purpose of a security control is to enforce it, and not to bypass it.