在重定向中包含 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]

不可接受的可能解决方法:

  1. 配置 Apache 在 RewriteRule 之前发送 CORS header:

    Header 总是设置 Access-Control-Allow-Origin "*"

这不是一个好的解决方案,因为我不想为所有 URL 发送这个 header 只有这个重定向。其他页面确实设置了这个 header 并且当 Chrome 收到多个具有相同值的 Access-Control-Allow-Origin header 时,会生成一个错误接受 headers。注意:AFAIK header 始终设置 需要包含 header 以进行 3xx 响应。

  1. 修改应用程序以使用重定向的 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。

Apache <If> Directive

Apache Server Variables

[更新]

通过使用 Access-Control-Allow-Origin "*" 响应,我的解决方案违背了 CORS 防止未经授权的资源共享的目的。此解决方案将在安全审计中触发警告或违规。因为我只是在后端通配特定路由而不是所有路由,所以这可以是 explained/documented.

当我在 Stack Overflow 和 Internet 上研究这个问题时,每个 answer/article 都建议返回 `Access-Control-Allow-Origin "*" header。这几乎是错误的解决方案。安全控制的目的是强制执行,而不是绕过它。