すべてのサブドメイン、ポート、プロトコルでCORSを有効にしようとしています。
たとえば、http: //sub.mywebsite.com : 8080 / からhttps://www.mywebsite.com/へのXHRリクエストを実行できるようにしたい*
通常、一致するオリジンからのリクエストを有効にします(制限されます)。
//*.mywebsite.com:*/*
すべてのサブドメイン、ポート、プロトコルでCORSを有効にしようとしています。
たとえば、http: //sub.mywebsite.com : 8080 / からhttps://www.mywebsite.com/へのXHRリクエストを実行できるようにしたい*
通常、一致するオリジンからのリクエストを有効にします(制限されます)。
//*.mywebsite.com:*/*
回答:
DaveRandomの回答に基づいて、私も試してみましたがAccess-Control-Allow-Origin
、書き換えルールを使用せずに、同じ結果(現在の特定のプロトコル+ドメイン+ポートに動的に設定される)を生成する少し単純なApacheソリューションを見つけました。
SetEnvIf Origin ^(https?://.+\.mywebsite\.com(?::\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.comなど)でCORSを有効にする場合は、最初の行の正規表現を次の正規表現に置き換えるだけです。
^(https?://(?:.+\.)?mywebsite\.com(?::\d{1,5})?)$
。
注:仕様への準拠と正しいキャッシュ動作のVary: Origin
ために、CORS非対応のリクエストや許可されていない送信元からのリクエストであっても、常にCORS対応リソースの応答ヘッダーを追加します(理由の例を参照)。
//
Apache confはスラッシュ区切りの正規表現を使用しないため、このコンテキストでをエスケープする必要はありません。Regexrは、そのコンテキストではスラッシュが区切り文字として特別な意味を持っているため、文句を言います。
The 'Access-Control-Allow-Origin' header contains multiple values '^(https?://(?:.+.)?aerofotea.com(?::d{1,5})?)$', but only one is allowed. Origin 'http://local.aerofotea.com' is therefore not allowed access.
CORS仕様はオールオアナッシングです。*
、null
または正確なプロトコル+ドメイン+ポートのみをサポートします:http : //www.w3.org/TR/cors/#access-control-allow-origin-response-header
サーバーは正規表現を使用して送信元ヘッダーを検証する必要があります。その後、Access-Control-Allow-Origin応答ヘッダーで送信元の値をエコーできます。
編集:これの代わりに@Noyoのソリューションを使用してください。負荷がかかった場合、よりシンプルで明確になり、パフォーマンスが向上する可能性があります。
元の回答は、歴史的な目的のためにここに残されました!!
私はこの問題をいくつか試し、Apacheで動作するこの再利用可能な.htaccess(またはhttpd.conf)ソリューションを思いつきました。
<IfModule mod_rewrite.c>
<IfModule mod_headers.c>
# Define the root domain that is allowed
SetEnvIf Origin .+ ACCESS_CONTROL_ROOT=yourdomain.com
# Check that the Origin: matches the defined root domain and capture it in
# an environment var if it does
RewriteEngine On
RewriteCond %{ENV:ACCESS_CONTROL_ROOT} !=""
RewriteCond %{ENV:ACCESS_CONTROL_ORIGIN} =""
RewriteCond %{ENV:ACCESS_CONTROL_ROOT}&%{HTTP:Origin} ^([^&]+)&(https?://(?:.+?\.)?\1(?::\d{1,5})?)$
RewriteRule .* - [E=ACCESS_CONTROL_ORIGIN:%2]
# Set the response header to the captured value if there was a match
Header set Access-Control-Allow-Origin %{ACCESS_CONTROL_ORIGIN}e env=ACCESS_CONTROL_ORIGIN
</IfModule>
</IfModule>
ACCESS_CONTROL_ROOT
ブロックの上部にある変数をルートドメインに設定するだけで、ドメインに一致する場合、Origin:
リクエストヘッダー値がAccess-Control-Allow-Origin:
応答ヘッダー値でクライアントにエコーバックされます。
また、sub.mydomain.com
として使用でき、ACCESS_CONTROL_ROOT
オリジンをsub.mydomain.com
andに制限します*.sub.mydomain.com
(つまり、ドメインルートである必要はありません)。変更が許可されている要素(プロトコル、ポート)は、正規表現のURIマッチング部分を変更することで制御できます。
受け入れられた答えは以下を行うことができないので、私はこの質問に答えています
例えば:それはのためにCORSヘッダを送信しませんhttp://mywebsite.comのための作品ながらhttp://somedomain.mywebsite.com/
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"
サイトを有効にするには、上記のApache設定で「mywebsite.com」の代わりにサイトを配置するだけです。
複数のサイトを許可するには:
SetEnvIf Origin "http(s)?://(.+\.)?(othersite\.com|mywebsite\.com)(:\d{1,5})?$" CORS=$0
展開後のテスト:
次のcurl応答には、変更後に「Access-Control-Allow-Origin」ヘッダーが含まれているはずです。
curl -X GET -H "Origin: http://examplesite1.com" --verbose http://examplesite2.com/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'),
preg_quote()
それが正しい方法であるために使用するために編集さ.
れました(DNS名で有効な唯一の正規表現メタ文字preg_quote()
は意図された操作をより適切に説明しています)
none
仕様に従って、がヘッダーの意味的に有効な値ではない(または少なくとも、それが意味することを行わない)ことを明確にする必要があります。そのreturn null;
ため、そのブランチにとっては意味があり、その場合はヘッダーをクライアントに送信してはならないので、呼び出し元がチェックする必要があります。
preg_quote()
*記号を引用するため、str_replace()
たとえば、孤立した「\」が残ります。
Access-Control-Allow-Origin
.htaccessで設定する場合、以下のみが機能しました:
SetEnvIf Origin "http(s)?://(.+\.)?domain\.com(:\d{1,5})?$" CRS=$0
Header always set Access-Control-Allow-Origin "%{CRS}e" env=CRS
私は他のいくつかの提案のキーワードを試してみましたHeader append
、Header set
、どれも働いていないこれらのキーワードが有効なため、古くなったりしない場合、私はわかりませんけれども、SOの多くの回答で提案されているようにnginxの。
これが私の完全な解決策です:
SetEnvIf Origin "http(s)?://(.+\.)?domain\.com(:\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]
「Cookieドメイン」(www.domain.tld)からフォントを読み取るときに、静的な「Cookieのない」ドメインでFont Awesomeに同様の問題があり、この投稿は私たちのヒーローでした。こちらをご覧ください:「クロスオリジンリソースシェアリング(CORS)応答ヘッダーがありません」というWebフォントの問題を修正するにはどうすればよいですか?
copy / paste-rタイプの場合(およびいくつかの小道具を与えるため)、これをすべてのコントリビューションからつなぎ合わせて、サイトルートの.htaccessファイルの先頭に追加しました。
<IfModule mod_headers.c>
<IfModule mod_rewrite.c>
SetEnvIf Origin "http(s)?://(.+\.)?(othersite\.com|mywebsite\.com)(:\d{1,5})?$" CORS=$0
Header set Access-Control-Allow-Origin "%{CORS}e" env=CORS
Header merge Vary "Origin"
</IfModule>
</IfModule>
超安全、超エレガント。それを愛する:リソースの泥棒/ホットリンクの種類にサーバーの帯域幅を開く必要はありません。
小道具:@Noyo @DaveRandom @ pratap-koritala
(私はこれを受け入れられた回答へのコメントとして残そうとしましたが、それはまだできません)
Spring Bootの場合、RegexCorsConfiguration
これは公式を拡張するものでしたCorsConfiguration
:https : //github.com/looorent/spring-security-jwt/blob/master/src/main/java/be/looorent/security/jwt/RegexCorsConfiguration.java
元の答えはApache 2.4より前のようでした。うまくいきませんでした。これは、2.4で機能させるために変更しなければならないものです。これは、yourcompany.comのサブドメインのどの深さでも機能します。
SetEnvIf Host ^((?:.+\.)*yourcompany\.com?)$ 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"
孤立したものが正規表現になってしまったため、実際のホスト(プロトコルやポートに注意を払っていない)のみを比較するために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']));
}