प्रवेश-नियंत्रण-अनुमति-मूल वाइल्डकार्ड उप-डोमेन, पोर्ट और प्रोटोकॉल


312

मैं सभी उप-डोमेन, पोर्ट और प्रोटोकॉल के लिए CORS को सक्षम करने का प्रयास कर रहा हूं।

उदाहरण के लिए, मैं http://sub.mywebsite.com:8080/ से https://www.mywebsite.com/ * पर XHR रिक्वेस्ट चलाने में सक्षम होना चाहता हूं ।

आमतौर पर, मैं मूल मिलान (और सीमित) से अनुरोध को सक्षम करना चाहूंगा:

//*.mywebsite.com:*/*

जवाबों:


207

डेवग्रैंडम के उत्तर के आधार पर , मैं भी खेल रहा था और थोड़ा सरल अपाचे समाधान पाया गया, जो Access-Control-Allow-Originकिसी भी पुनर्लेखन नियमों का उपयोग किए बिना एक ही परिणाम ( वर्तमान विशिष्ट प्रोटोकॉल + डोमेन + पोर्ट पर गतिशील रूप से सेट) है:

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})?)$

नोट: अटकलें अनुपालन और सही कैशिंग व्यवहार के लिए, ALWAYS Vary: Originकॉर्स-सक्षम संसाधनों के लिए प्रतिक्रिया शीर्षलेख जोड़ते हैं , यहां तक ​​कि गैर-कोर अनुरोधों के लिए और एक अस्वीकृत मूल से ( उदाहरण देखें क्यों )।


1
हमारे पास लगभग यही था (वैरी ओरिजिन नहीं) और खराब व्यवहार मिला जब आगंतुक एक ही फ़ॉन्ट का उपयोग करके कई उप डोमेन के बीच कूद गए। फ़ॉन्ट और पहुँच-नियंत्रण-मूल शीर्षलेख भी कैश किया गया था। मैंने इस पर थोड़ा परिवर्तन किया है: मैं "एक्सेस-कंट्रोल-अनुमति-उत्पत्ति *" का उपयोग करता हूं यदि अनुरोध हमारे स्वीकृत डोमेन में से एक है। शायद यह "वैरी ओरिजिन" के साथ हल किया गया था जो हमारे पास पहले नहीं था ... अब इसमें भी जोड़ा गया है।
एरिक मेलकर्सन

2
मूल डोमेन 'mywebsite.com' के लिए काम नहीं करता है
biology.info

1
@pgmann, //इस संदर्भ में बचने की कोई आवश्यकता नहीं है , क्योंकि Apache conf में स्लैश-सीमांकित नियमित अभिव्यक्तियों का उपयोग नहीं किया गया है। Regexr शिकायत करता है, क्योंकि उस संदर्भ में, स्लैम का अर्थ सीमांकक के रूप में विशेष है।
नॉयो

1
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.
एयरो वांग

3
आप इस कोड को कहां रखते हैं? .htaccess या अपाचे आभासी मेजबान विन्यास में?
ग्लेन

252

CORS कल्पना ऑल-ऑर-नथिंग है। यह केवल समर्थन करता है *, nullया सटीक प्रोटोकॉल + डोमेन + पोर्ट: http://www.w3.org/TR/cors/#access-control-allow-origin-response-header

आपके सर्वर को regex का उपयोग करके मूल शीर्षलेख को मान्य करना होगा, और उसके बाद आप Access-Control-Allow-Origin प्रतिक्रिया शीर्ष लेख में मूल मान को प्रतिध्वनित कर सकते हैं।


7
@Dexter "null" का उपयोग "null" मूल के जवाब में किया जा सकता है, उदाहरण के लिए जब एक फ़ाइल से एक CORS अनुरोध: // योजना।
मोनसुर

130
यह गहराई से पता चला है कि कॉर्स कल्पना ओपी के सटीक उपयोग-मामले का समर्थन नहीं करेगी ।
एरोथ

6
@ बरोठा: वास्तव में नहीं, कल्पना कार्यान्वयन को किसी भी मिलान वाक्यविन्यास का उपयोग करने की अनुमति देती है जो वे चाहते हैं; यह केवल इस उपयोग के मामले का समर्थन नहीं करने के लिए एक कार्यान्वयन के लिए गहरा होगा । दूसरे शब्दों में, जो आप अपने सर्वर को निर्दिष्ट करते हैं वह एसीएओ मूल्य नहीं है, बाद वाला सिर्फ एक प्रोटोकॉल विवरण है। मेरी धारणा यह है कि एक सुरक्षा परिदृश्य है जिसकी आवश्यकता या लाभ मूल से वापस प्रतिध्वनित होता है, लेकिन एक भोली कार्यान्वयन केवल "ओके" कहकर काम करता है या नहीं।
tne

3
2015 से अपडेट: इस उत्तर को हानिकारक माना जाना चाहिए, क्योंकि यह अपूर्ण है और कैशिंग मुद्दों को जन्म दे सकता है। : कृपया (अपाचे के लिए) एक उचित कार्यान्वयन और विवरण के लिए नीचे मेरी जवाब देखने stackoverflow.com/a/27990162/357774 । इसके अलावा, @ थर्थ, जैसा कि बताते हैं, वास्तव में ओपी के सटीक उपयोग के मामले की कल्पना करता है : w3.org/TR/cors/#resource-implementation । और जैसा कि यह उत्तर बताता है, इसे लागू करने के लिए सर्वर पर निर्भर है। यह 3 लाइनों में किया जा सकता है, जैसा कि ऊपर वर्णित उत्तर में देखा गया है।
नोयो

19
@ नोयो - मैं अपना मूल अर्थ फिर स्पष्ट करूँगा। यह गहराई से पता चला है कि कॉर्स की युक्ति को उन सभी सर्वरों की कड़ाई से आवश्यकता नहीं है जो ओपी के सटीक उपयोग के मामले में स्वचालित, अंतर्निहित समर्थन प्रदान करने के लिए कॉर्स को लागू करते हैं । कस्टम PHP कोड का उपयोग करके अपने स्वयं के शिम का निर्माण करने के लिए प्रत्येक व्यक्तिगत उपयोगकर्ता पर छोड़ देना, नियमों को फिर से लिखना, या क्या है-आपके पास विखंडन, कीड़े और आपदा के लिए एक नुस्खा है। सर्वर देवों को इससे बेहतर पता होना चाहिए; और यदि वे नहीं करते हैं, तो CORS कल्पना उन्हें बाध्य करना चाहिए।
एरोथ

59

संपादित करें : इस के बजाय @ नोयो के समाधान का उपयोग करें । यह सरल, स्पष्ट है और लोड के तहत बहुत अधिक प्रदर्शन की संभावना है।

केवल व्यावसायिक इतिहास के लिए मूल उत्तर छोड़ दिया !!


मैंने इस मुद्दे के साथ कुछ खेल किया और इस पुन: प्रयोज्य .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और *.sub.mydomain.com(यानी यह डोमेन जड़ होना जरूरी नहीं है)। जिन तत्वों को अलग-अलग करने की अनुमति है (प्रोटोकॉल, पोर्ट) को रेगेक्स के यूआरआई मिलान वाले हिस्से को संशोधित करके नियंत्रित किया जा सकता है।


22

मैं इस प्रश्न का उत्तर दे रहा हूं, क्योंकि स्वीकृत उत्तर निम्नलिखित नहीं कर सकता है

  1. regex समूहीकरण एक प्रदर्शन हिट है , जो आवश्यक नहीं है।
  2. प्राथमिक डोमेन से मेल नहीं खा सकता है और यह केवल उप डोमेन के लिए काम करता है।

उदाहरण के लिए: http://somedomain.mywebsite.com/ के लिए काम करते समय यह http://mywebsite.com के लिए CORS हेडर नहीं भेजेगा।

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.com" के स्थान पर अपनी साइट डालें।

एकाधिक साइटों को अनुमति देने के लिए:

SetEnvIf Origin "http(s)?://(.+\.)?(othersite\.com|mywebsite\.com)(:\d{1,5})?$" CORS=$0

परीक्षण के बाद तैनाती:

निम्नलिखित कर्ल प्रतिक्रिया में परिवर्तन के बाद "एक्सेस-कंट्रोल-अनुमति-उत्पत्ति" हेडर होना चाहिए।

curl -X GET -H "Origin: http://examplesite1.com" --verbose http://examplesite2.com/query

12

मुझे एक 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'),

1
+1, उपयोग करने के लिए संपादित किया गया है, preg_quote()क्योंकि ऐसा करने का सही तरीका है (भले ही .DNS नाम में एकमात्र regexp मेटा चार वैध है, preg_quote()इच्छित ऑपरेशन का बेहतर वर्णन करता है)
डेवग्रैंडमन

1
यह स्पष्ट किया जाना चाहिए कि noneहेडर के लिए शब्दार्थ मान्य मूल्य नहीं है (या कम से कम, ऐसा नहीं करता है जो इसका मतलब है) कल्पना के अनुसार। जैसे, return null;उस शाखा के लिए और अधिक समझ हो सकती है, और उस स्थिति में ग्राहक को कोई हेडर नहीं भेजा जाना चाहिए, इसलिए इसे कॉलर द्वारा चेक किया जाना चाहिए।
डेवग्रैंडम जूल

preg_quote()* संकेत को उद्धृत करेगा और इसलिए str_replace()उदाहरण के लिए एक अनाथ "\" को छोड़ देता है।
क्रिस्टोफर बुबाक

1
यह उपयोगी है, मैंने कॉर्स मुद्दे पर तब तक समय बिताया जब तक मुझे एहसास नहीं हुआ कि मेरी साइट अजाक्स में "www" थी, लेकिन पर्मलिंक संरचना में नहीं - आपके समाधान ने मुझे यह समझने में मदद की कि समस्या कहां थी और मेरे लिए यह हल था।
सोल

3

जब 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, भी काम नहीं किया के रूप में इतने पर कई सवालों के जवाब में सुझाव दिया है, हालांकि मुझे पता नहीं है कि इन कीवर्ड को पुराने हो गए हैं या के लिए मान्य नहीं है, तो 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]

2

जब हम "कुकी डोमेन" (www.domain.tld) ​​से फ़ॉन्ट पढ़ रहे थे, तो एक स्थिर "कुकी-कम" डोमेन पर फ़ॉन्ट विस्मय के साथ समान मुद्दे थे और यह पोस्ट हमारा हीरो था। यहां देखें: मैं 'मिसिंग क्रॉस-ओरिजिनल रिसोर्स शेयरिंग (कॉर्स) रिस्पॉन्स हेडर' वेबफोंट मुद्दे को कैसे ठीक कर सकता हूं?

कॉपी / पेस्ट-आर प्रकारों के लिए (और कुछ प्रॉप्स देने के लिए) मैंने इसे सभी योगदानों से एक साथ जोड़ दिया और इसे साइट रूट की .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 @ प्रताप-कोरिताला

(मैंने इसे स्वीकृत उत्तर के लिए एक टिप्पणी के रूप में छोड़ने की कोशिश की, लेकिन मैं अभी तक ऐसा नहीं कर सकता)



0

ऐसा लगता है कि मूल उत्तर पूर्व अपाचे 2.4 के लिए था। यह मेरे लिए सही नहीं रहा। यहां बताया गया है कि 2.4 में काम करने के लिए मुझे क्या बदलना होगा। यह आपके subcompain.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"

0

मुझे संशोधित करना था लार्स के उत्तर को थोड़ा , क्योंकि एक अनाथ को रेक्सएक्स में \समाप्त कर दिया गया था, केवल वास्तविक मेजबान (प्रोटोकॉल या पोर्ट पर ध्यान नहीं दे रहा) की तुलना करने के लिए और मैं 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']));
}

0

मेरे मामले में कोणीय का उपयोग कर

मेरे HTTP इंटरसेप्टर में, मैंने सेट किया

with Credentials: true.

अनुरोध के शीर्ष लेख में

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.