如何启用 CORS 的 Apache Web 服务器(包括预检和自定义标头)?

Posted

技术标签:

【中文标题】如何启用 CORS 的 Apache Web 服务器(包括预检和自定义标头)?【英文标题】:How to CORS-enable Apache web server (including preflight and custom headers)? 【发布时间】:2017-07-22 08:15:35 【问题描述】:

一般:

Request URL:x/site.php
Request Method:OPTIONS
Status Code:302 Found
Remote Address:x.x.x.x:80

响应标头:

view source
Access-Control-Allow-Headers:Content-Type
Access-Control-Allow-Origin:*
Access-Control-Max-Age:300
Cache-Control:no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Content-Length:0
Content-Type:text/html; charset=UTF-8
Date:Thu, 02 Mar 2017 14:27:21 GMT
Expires:Thu, 19 Nov 1981 08:52:00 GMT
Location:y
Pragma:no-cache
Server:Apache/2.4.25 (Ubuntu)

请求标头:

view source
Accept:*/*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:en-US,en;q=0.8
Access-Control-Request-Headers:authorization
Access-Control-Request-Method:POST
Cache-Control:no-cache
Connection:keep-alive
DNT:1
Host:x
Origin:http://127.0.0.1:3000
Pragma:no-cache
Referer:http://127.0.0.1:3000/
User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.90 Safari/537.36

Apache 虚拟主机配置如下:

    <IfModule mod_headers.c>
           Header set Access-Control-Allow-Origin "http://127.0.0.1:3000"
           Header set Access-Control-Allow-Origin "http://127.0.0.1"
           Header set Access-Control-Max-Age "300"
           Header set Access-Control-Allow-Credentials "true"
           Header set Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept"
           Header set Access-Control-Allow-Methods "POST, GET, PUT, DELETE, PATCH, OPTIONS"
    </IfModule>

预检请求跳过 apache 配置并直接点击我的 webapp,这会进行重定向(因此是 302 和位置:y)。

不知道为什么 apache 不处理预检请求?

【问题讨论】:

【参考方案1】:

要完全启用 CORS 的 Apache Web 服务器,您需要将其配置为如下所示:

Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Headers "Authorization"
Header always set Access-Control-Allow-Methods "GET"
Header always set Access-Control-Expose-Headers "Content-Security-Policy, Location"
Header always set Access-Control-Max-Age "600"

RewriteEngine On
RewriteCond %REQUEST_METHOD OPTIONS
RewriteRule ^(.*)$ $1 [R=200,L]

https://benjaminhorn.io/code/setting-cors-cross-origin-resource-sharing-on-apache-with-correct-response-headers-allowing-everything-through/的详细解释

关于为各种Access-Control- 响应标头设置什么值的一些一般说明:

Access-Control-Allow-Headers:您必须将其设置为包含您的请求发送的任何标头名称​​除了    CORS-safelisted header names 或所谓的“forbidden” header names(标头名称由您无法在 javascript 中设置的浏览器); the spec alternatively allows the * wildcard 作为它的值——所以你可以试试,虽然有些浏览器可能还不支持它:Chrome bug、Firefox bug、Safari bug

Access-Control-Allow-Methods:the spec alternatively allows the * wildcard——但同样,与Access-Control-Allow-Headers: *一样,一些浏览器可能还不支持它。

Access-Control-Expose-Headers:设置为包含您的前端代码需要的ExpiresCache-ControlContent-TypePragmaLast-ModifiedContent-Language 之外的任何响应标头阅读。很多人忘记设置它,最终对为什么他们无法读取特定响应标头的值感到困惑)。再次the spec alternatively allows the * wildcard 这里,但有些浏览器可能还不支持它。

Access-Control-Max-Age:Chrome 的上限为 600(10 分钟)hardcoded,因此没有必要为它设置更高的值(Chrome 只会限制它如果您将其设置得更高,则可以缩短到 10 分钟,而 Safari 将其限制为仅 5 分钟)。


那么,关于问题中显示的特定请求,需要进行的具体更改和添加如下:

使用Header always set 而不仅仅是Header set

使用mod_rewrite 处理OPTIONS,只需发回带有这些标头的200 OK

请求有 Access-Control-Request-Headers:authorization 所以在 Apache 配置中,也要在 Access-Control-Allow-Headers 响应头中添加 Authorization

Origin 是浏览器设置的“禁止”标头名称,Accept 是 CORS 安全列表中的标头名称,因此无需将它们包含在 Access-Control-Allow-Headers 中。

请求不发送Content-Type,因此在响应中的Access-Control-Allow-Headers 中不需要它(GET 请求不需要它,否则只有在类型不是application/x-www-form-urlencodedtext/plainmultipart/form-data)。

对于Access-Control-Allow-Methods,请求似乎只是一个GET,所以除非计划也提出POST/PUT/DELETE/PATCH 请求,否则包括它们是没有意义的。

【讨论】:

谢谢!对我有用/有意义的许多帖子中的第一个。 拥有 Header always set Access-Control-Allow-Origin "*" 似乎违背了 CORS 的观点。 @ChrisStryczynski 请参阅***.com/a/43154277/441757 的答案。我知道有一些指南/消息来源断言或暗示 CORS 的目的是阻止其他网站访问您的内容。但这实际上根本不是 CORS 的重点——相反,CORS 的重点是防止特权升级攻击。例如,请参阅***.com/a/29167709/441757 的答案。如果您的网站不使用/不需要凭据进行访问,则无需防止特权升级攻击 — Access-Control-Allow-Origin: * 可以安全使用。 @ChrisStryczynski CORS 实际上并不是一种阻止从其他站点对您的内容的所有访问的方法,实际上 CORS 根本不是阻止从其他站点对您的内容的所有访问的有效方法网站——因为您的内容仍然可以从服务器端后端代码访问。因此,对于任何确实想要阻止访问的人来说,设置某种身份验证机制是正确的方法——因为这也会阻止来自服务器端后端代码的访问。 问题或答案都没有说明这个通配符 - 所以理想情况下应该提到这个警告。

以上是关于如何启用 CORS 的 Apache Web 服务器(包括预检和自定义标头)?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 JBoss AS 上使用 java RESTful Web 服务启用 CORS

如何在 jBoss 中启用 CORS

在 Java Web 服务中启用 CORS

如何使用 Flask-Restless 启用 CORS

在 Visual Studio 开发服务器上为 Soap Web 服务启用 CORS 设置

Azure 移动服务 Web Api 上的 SignalR CORS