如何CORS-enable Apache 网络服务器(包括预检和自定义headers)?

How to CORS-enable Apache web server (including preflight and custom headers)?

一般:

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

响应Headers:

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)

请求Headers:

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 没有处理预检请求?

要完全 CORS-enable 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 ^(.*)$  [R=200,L]

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

有更详细的解释

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

  • Access-Control-Allow-Headers:您必须将其设置为包括您的请求发送的任何 header 名称 except CORS-safelisted header names or so-called “forbidden” header names (names of headers set by the browser that you can’t set in your JavaScript); the spec alternatively allows the * wildcard as its value—so you can try it, though some browsers may not support it yet: Chrome bug, Firefox bug, Safari bug.

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

  • Access-Control-Expose-Headers:设置为包括超过 ExpiresCache-Control 的任何响应 headers,您的前端代码需要读取的 Content-TypePragmaLast-ModifiedContent-Language。很多人忘记设置它并最终对为什么他们无法读取特定响应的值感到困惑header)。再次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 与那些 header 一起发回即可。

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

  • Origin是浏览器设置的“禁止”header名称,Accept是CORS-safelistedheader名称, 因此无需将它们包含在 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 个请求,没有必要包含它们。