我正在尝试为所有子域,端口和协议启用CORS。
例如,我希望能够从http://sub.mywebsite.example:8080/到https://www.mywebsite.example/*运行XHR请求
通常情况下,我想启用来自源匹配的请求(并且仅限于):
/ / * .mywebsite.example: * / *
我正在尝试为所有子域,端口和协议启用CORS。
例如,我希望能够从http://sub.mywebsite.example:8080/到https://www.mywebsite.example/*运行XHR请求
通常情况下,我想启用来自源匹配的请求(并且仅限于):
/ / * .mywebsite.example: * / *
当前回答
CORS规范是全有或全无。只支持*、null或精确的协议+域+端口:http://www.w3.org/TR/cors/#access-control-allow-origin-response-header
您的服务器将需要使用正则表达式验证原点标头,然后您可以在Access-Control-Allow-Origin响应标头中回显原点值。
其他回答
我在回答这个问题,因为公认的答案做不到跟随
正则表达式分组会影响性能,但这是不必要的。 不能匹配主域,只适用于子域。
例如:它不会为http://mywebsite.example发送CORS头,而为http://somedomain.mywebsite.example/工作
SetEnvIf Origin "http(s)?://(.+\.)?mywebsite\.com(:\d{1,5})?$" CORS=$0
Header set Access-Control-Allow-Origin "%{CORS}e" env=CORS
Header merge Vary "Origin"
要启用你的网站,你只是把你的网站在mywebsite的地方。在上面的Apache配置的例子。
允许多个站点:
SetEnvIf Origin "http(s)?://(.+\.)?(othersite\.com|mywebsite\.example)(:\d{1,5})?$" CORS=$0
部署后验证:
下面的curl响应在更改后应该具有“Access-Control-Allow-Origin”标头。
curl -X GET -H "Origin: http://site1.example" --verbose http://site2.example/query
我需要一个只有php的解决方案,所以以防有人也需要它。它接受一个允许的输入字符串,如“*.example.com”,如果输入匹配,则返回请求头服务器名。
function getCORSHeaderOrigin($allowed, $input)
{
if ($allowed == '*') {
return '*';
}
$allowed = preg_quote($allowed, '/');
if (($wildcardPos = strpos($allowed, '*')) !== false) {
$allowed = str_replace('*', '(.*)', $allowed);
}
$regexp = '/^' . $allowed . '$/';
if (!preg_match($regexp, $input, $matches)) {
return 'none';
}
return $input;
}
下面是phpunit数据提供程序的测试用例:
// <description> <allowed> <input> <expected>
array('Allow Subdomain', 'www.example.com', 'www.example.com', 'www.example.com'),
array('Disallow wrong Subdomain', 'www.example.com', 'ws.example.com', 'none'),
array('Allow All', '*', 'ws.example.com', '*'),
array('Allow Subdomain Wildcard', '*.example.com', 'ws.example.com', 'ws.example.com'),
array('Disallow Wrong Subdomain no Wildcard', '*.example.com', 'example.com', 'none'),
array('Allow Double Subdomain for Wildcard', '*.example.com', 'a.b.example.com', 'a.b.example.com'),
array('Don\'t fall for incorrect position', '*.example.com', 'a.example.com.evil.com', 'none'),
array('Allow Subdomain in the middle', 'a.*.example.com', 'a.bc.example.com', 'a.bc.example.com'),
array('Disallow wrong Subdomain', 'a.*.example.com', 'b.bc.example.com', 'none'),
array('Correctly handle dots in allowed', 'example.com', 'exampleXcom', 'none'),
对我来说,我想要一个多域选项,这就是我使用的解决方案,使用python和flask,
VALID_DOMAINS = 'https://subdomain1.example.com', 'https://subdomain2.example.com'
def handle_request(request):
origin = request.headers.get('Origin')
if request.method == 'OPTIONS':
if origin not in :
return ''
headers = {
'Access-Control-Allow-Origin': origin,
'Access-Control-Allow-Methods': 'GET',
'Access-Control-Allow-Headers': 'Content-Type',
'Access-Control-Max-Age': '3600',
}
return '', 204, headers
return (
main_function_with_logic(request),
200,
{'Access-Control-Allow-Origin': origin,
...}
)
显然,您可以将VALID_DOMAINS扩展到任意您想要的长度,以及任何您想要的(非https、不同端口等),并在请求上进行检查。
与通配符解决方案相比,我更喜欢这种解决方案,因此这是我在运行的服务器上的选择。
在我的例子中使用的是angular
在我的HTTP拦截器,我设置
with Credentials: true.
在请求头中
根据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请求和来自不允许的源的请求也是如此(参见示例原因)。