我正在尝试为所有子域,端口和协议启用CORS。

例如,我希望能够从http://sub.mywebsite.example:8080/到https://www.mywebsite.example/*运行XHR请求

通常情况下,我想启用来自源匹配的请求(并且仅限于):

/ / * .mywebsite.example: * / *


当前回答

看起来最初的答案是在Apache 2.4之前。这对我没用。下面是我为了让它在2.4中正常工作所做的修改。这将适用于你公司的任何深度的子域。

SetEnvIf Host ^((?:.+\.)*yourcompany\.example?)$    CORS_ALLOW_ORIGIN=$1
Header append Access-Control-Allow-Origin  %{REQUEST_SCHEME}e://%{CORS_ALLOW_ORIGIN}e    env=CORS_ALLOW_ORIGIN
Header merge  Vary "Origin"

其他回答

在我的例子中使用的是angular

在我的HTTP拦截器,我设置

with Credentials: true.

在请求头中

我不得不稍微修改Lars的回答,因为正则表达式中出现了一个孤立的\,只比较实际的主机(不注意协议或端口),我想在我的生产域之外支持localhost域。因此,我将$allowed参数更改为一个数组。

    function getCORSHeaderOrigin($allowed, $input)
    {
        if ($allowed == '*') {
            return '*';
        }
    
        if (!is_array($allowed)) {
            $allowed = array($allowed);
        }
    
        foreach ($allowed as &$value) {
            $value = preg_quote($value, '/');
    
            if (($wildcardPos = strpos($value, '\*')) !== false) {
                $value = str_replace('\*', '(.*)', $value);
            }
        }
    
        $regexp = '/^(' . implode('|', $allowed) . ')$/';
    
        $inputHost = parse_url($input, PHP_URL_HOST);
    
        if ($inputHost === null || !preg_match($regexp, $inputHost, $matches)) {
            return 'none';
        }
    
        return $input;
    }

用法如下:

    if (isset($_SERVER['HTTP_ORIGIN'])) {
        header("Access-Control-Allow-Origin: " . getCORSHeaderOrigin(array("*.myproduction.com", "localhost"), $_SERVER['HTTP_ORIGIN']));
    }

当在.htaccess中设置Access-Control-Allow-Origin时,只有以下几种有效:

SetEnvIf Origin "http(s)?://(.+\.)?domain\.example(:\d{1,5})?$" CRS=$0
Header always set Access-Control-Allow-Origin "%{CRS}e" env=CRS

我尝试了其他几个建议的关键字头追加,头集,没有工作建议在Stack Overflow上的许多答案,虽然我不知道这些关键字是否过时或对nginx无效。

以下是我的完整解决方案:

SetEnvIf Origin "http(s)?://(.+\.)?domain\.example(:\d{1,5})?$" CRS=$0
Header always set Access-Control-Allow-Origin "%{CRS}e" env=CRS
Header merge Vary "Origin"

Header always set Access-Control-Allow-Methods "GET, POST"
Header always set Access-Control-Allow-Headers: *

# Cached for a day
Header always set Access-Control-Max-Age: 86400

RewriteEngine On

# Respond with 200OK for OPTIONS
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule ^(.*)$ $1 [R=200,L]

对于Spring Boot,我发现这个RegexCorsConfiguration扩展了官方的CorsConfiguration: https://github.com/looorent/spring-security-jwt/blob/master/src/main/java/be/looorent/security/jwt/RegexCorsConfiguration.java

根据daverrandom的回答,我也在玩,找到了一个稍微简单一点的Apache解决方案,它产生了相同的结果(Access-Control-Allow-Origin被动态地设置为当前特定的协议+域+端口),而不使用任何重写规则:

SetEnvIf Origin ^(https?://.+\.mywebsite\.example(?::\d{1,5})?)$   CORS_ALLOW_ORIGIN=$1
Header append Access-Control-Allow-Origin  %{CORS_ALLOW_ORIGIN}e   env=CORS_ALLOW_ORIGIN
Header merge  Vary "Origin"

就是这样。

那些想要在父域(例如mywebsite.example)以及所有子域上启用CORS的人可以简单地将第一行中的正则表达式替换为:

^ (https ?://(?:.+\.)? mywebsite \ .example (?:: \ d{1, 5}) ?)美元。

注意:为了符合规范和正确的缓存行为,ALWAYS为启用cors的资源添加Vary: Origin响应头,即使对于非cors请求和来自不允许的源的请求也是如此(参见示例原因)。