如何启用 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
:设置为包含您的前端代码需要的Expires
、Cache-Control
、Content-Type
、Pragma
、Last-Modified
和 Content-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-urlencoded
、text/plain
或multipart/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