httpd duplicate Access-Control-Allow-Origin with “

2020-03-30 04:14发布

问题:

I am trying to enable CORS on my server. It hosts both an Apache HTTPD and an Apache Tomee. HTTPD is configured as:

SetEnvIf Origin "^https://(.+\.)?my-domain.com$" allowed_origin=$0
Header always set Access-Control-Allow-Origin %{allowed_origin}e env=allowed_origin
Header set Access-Control-Allow-Credentials "true"
Header set Access-Control-Allow-Methods "GET, POST, OPTIONS, HEAD, PUT, DELETE, PATCH"
Header set Access-Control-Allow-Headers "accept,x-requested-method,origin,x-requested-with,x-request,cache-control,content-type"
Header set Access-Control-Max-Age "600"

and my Tomee web XML :

<filter>
  <filter-name>CorsFilter</filter-name>
  <filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
  <init-param>
    <param-name>cors.allowed.headers</param-name>
    <param-value>Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Accept-Language,Keep-Alive</param-value>
  </init-param>
  <init-param>
    <param-name>cors.allowed.methods</param-name>
    <param-value>GET,POST,HEAD,OPTIONS,PUT,PATCH,DELETE</param-value>
  </init-param>
</filter>
<filter-mapping>
  <filter-name>CorsFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

My problem is I get the Access-Control-Allow-Credentials header twice in the response to the preflight OPTIONS request :

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://my-origin.my-domain.com
Access-Control-Allow-Origin: https://my-origin.my-domain.com
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 600
Access-Control-Allow-Methods: GET, POST, OPTIONS, HEAD, PUT, DELETE, PATCH
Access-Control-Allow-Headers: accept,x-requested-method,origin,x-requested-with,x-request,cache-control,content-type,authorization

I don't understand why the usage of the set keyword in my HTTPD configuration does not remove the duplicate Access-Control-Allow-Origin. Moreover, if I remove the 'always' keyword it returns one Access-Control-Allow-Origin only...

回答1:

Experiencing a similar issue. Spent a lot of time in debugging.

It is a bug in Apache. A failure of the internal design and a failure to document it.

Header [table] set [cookie] [value] [...]

That's the command to manipulate headers. There are at least two cookie tables in apache.

  • onsuccess, default, used for 20X status codes.
  • always, used for errors, including redirects codes.

Judging by my experience in the wild, all cookies from all tables are appended to the response.

In your example, the cookie set by Tomcat is in the onsuccess table, the cookie sets in apache is in the always table. The response gets both cookies, hence the duplication.

It gets more messy than that. The tables have different meaning depending on what modules are in use. For instance, when using proxy or CGI, the relevant table for cookies is onsuccess if the upstream server delivers an error successfully, but always if an internal apache error occurs.

This behavior is not documented. That seems not intentional but a consequence of apache internals. In the current state, it is basically impossible to manipulate headers properly with Apache.



回答2:

The accepted answer is correct. This is just a way of handling it that I've been using.

SetEnvIf Origin "^(.*(\.yoursite.com)[:0-9]*)$" cors=$1
# wash out these headers in the 'onsuccess' table if we get them from the backend
Header onsuccess unset Access-Control-Allow-Origin env=cors
Header onsuccess unset Access-Control-Allow-Credentials env=cors
Header onsuccess unset Access-Control-Allow-Methods env=cors
Header onsuccess unset Access-Control-Allow-Headers env=cors
# add them to the 'always' table
Header always set Access-Control-Allow-Origin %{cors}e env=cors
Header always set Access-Control-Allow-Credentials "true" env=cors
Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, PUT, DELETE" env=cors
Header always set Access-Control-Allow-Headers "accept,x-requested-method,origin" env=cors