javascript - enable - no 'access-control-allow-origin' header is present on the requested resource.




كيف يعمل رأس Access-Control-Allow-Origin؟ (8)

على ما يبدو ، لقد أساءت فهمها تمامًا لدلالاتها. فكرت في شيء من هذا القبيل:

  1. يقوم عميل بتحميل كود جافا سكريبت MyCode.js من http: // siteA - المصدر .
  2. يحتوي رأس استجابة MyCode.js على Access-Control-Allow-Origin: http: // siteB ، والذي أعتقد أنه يعني أنه تم السماح لـ MyCode.js بإنشاء مراجع عبر أصل لموقع B.
  3. يقوم العميل بتشغيل بعض وظائف MyCode.js ، والتي بدورها تقدم طلبات إلى http: // siteB ، والتي يجب أن تكون جيدة ، على الرغم من كونها طلبات عبر أصل.

حسنا ، أنا على خطأ. لا يعمل مثل هذا على الإطلاق. ﻟذا ، ﻗرأت ﻣﺷﺎرﻛﺔ ﻣﺻﺎدر ﻋﺑر اﻟﻣﻧﺷﺄ وﺣﺎوﻟت ﻗراءة ﻣﺷﺎرﻛﺔ ﻣﺻدر اﻟﻣﻧﺷﺄة اﻟﻌﺿوﯾﺔ ﻓﻲ ﺗوﺻﯾﺔ w3c

شيء واحد مؤكد - ما زلت لا أفهم كيف من المفترض استخدام هذا العنوان.

لديّ تحكم كامل في كلٍّ من الموقع "أ" و "الموقع" ب. كيف أقوم بتمكين شفرة جافا سكريبت التي تم تنزيلها من الموقع "أ" للوصول إلى الموارد على الموقع "ب" باستخدام هذا العنوان؟

PS

أنا لا أريد الاستفادة من JSONP.


أنا أعمل مع صريحة 4 والعقدة 7.4 وزاوية ، كان لي نفس المشكلة لي مساعدة هذا:
أ) جانب الخادم: في ملف app.js أعطي رؤوسًا لجميع الردود مثل:

app.use(function(req, res, next) {  
      res.header('Access-Control-Allow-Origin', req.headers.origin);
      res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
      next();
 });  

هذا يجب أن يكون قبل كل جهاز التوجيه .
رأيت الكثير من إضافة هذه الرؤوس:

res.header("Access-Control-Allow-Headers","*");
res.header('Access-Control-Allow-Credentials', true);
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');

لكنني لا أحتاج ذلك ،
ب) جانب العميل: في إرسال ajax تحتاج إلى إضافة: "withCredentials: true،" مثل:

$http({
     method: 'POST',
     url: 'url, 
     withCredentials: true,
     data : {}
   }).then(function(response){
        // code  
   }, function (response) {
         // code 
   });

حظا طيبا وفقك الله.


إذا كنت ترغب فقط في اختبار تطبيق عبر نطاق يعمل فيه المتصفح على حظر طلبك ، فيمكنك فتح المتصفح في الوضع غير الآمن واختبار التطبيق بدون تغيير التعليمات البرمجية ودون جعل الشفرة غير آمنة. من MAC OS يمكنك القيام بذلك من خط النهاية:

open -a Google\ Chrome --args --disable-web-security --user-data-dir

السؤال قديم جدًا ولا يمكن الإجابة عنه ، ولكني أقوم بنشر هذا السؤال لأي إشارة مستقبلية لهذا السؤال.

وفقًا لمقالة شبكة مطوري برامج Mozilla ،

يجعل المورد طلب HTTP عبر أصل عندما يطلب موردًا من نطاق مختلف ، أو منفذًا من الذي يقدمه المورد الأول نفسه.

تعمل صفحة HTML التي يتم عرضها من http://domain-a.com طلب <img> src http://domain-b.com/image.jpg .
اليوم العديد من الصفحات على شبكة الإنترنت تحميل الموارد مثل صفحات الأنماط CSS والصور والنصوص من المجالات منفصلة (وبالتالي يجب أن يكون باردا).

سياسة المنشأ نفسها

لأسباب تتعلق بالأمان ، تقوم المتصفحات بتقييد طلبات HTTP عبر أصل تبدأ من داخل البرامج النصية .
على سبيل المثال ، تتبع XMLHttpRequest و Fetch نهج الأصل نفسه .
لذلك ، يمكن لتطبيق الويب باستخدام XMLHttpRequest أو Fetch جعل طلبات HTTP فقط إلى مجاله الخاص .

مشاركة الموارد عبر المنشأ (CORS)

لتحسين تطبيقات الويب ، طلب المطورون من متصفّحي المتصفح السماح بالطلبات عبر النطاقات.

توفر آلية مشاركة الموارد عبر المنشأ (CORS) خوادم الوصول عبر الإنترنت لخوادم الويب ، والتي تمكن عمليات نقل البيانات عبر النطاق الآمن.
تستخدم المتصفحات الحديثة CORS في حاوية API - مثل XMLHttpRequest أو Fetch - للتخفيف من مخاطر طلبات HTTP المتشعبة.

كيفية عمل CORS ( Access-Control-Allow-Origin )

Wikipedia :

يصف معيار CORS عناوين HTTP الجديدة التي توفر للمتصفحات والخوادم طريقة لطلب عناوين URL بعيدة فقط عندما يكون لديهم إذن.

على الرغم من إمكانية إجراء بعض عمليات التحقق والتخويل من قِبل الخادم ، إلا أنه عادة ما يتحمل المتصفح مسؤولية دعم هذه العناوين وتكريم القيود التي تفرضها.

مثال

  1. يرسل المستعرض طلب OPTIONS مع رأس Origin HTTP .

    قيمة هذا الرأس هي النطاق الذي يخدم الصفحة الرئيسية. عندما تحاول صفحة من http://www.example.com الوصول إلى بيانات المستخدم في service.example.com ، سيتم إرسال عنوان الطلب التالي إلى service.example.com :

    المنشأ: http://www.example.com

  2. قد يرد الخادم على service.example.com مع:

    • عنوان Access-Control-Allow-Origin (ACAO) في الرد يشير إلى مواقع الأصل المسموح بها.
      فمثلا:

      Access-Control-Allow-Origin: http://www.example.com

    • صفحة خطأ إذا كان الخادم لا يسمح بالطلب عبر أصل

    • عنوان Access-Control-Allow-Origin (ACAO) مع حرف بدل يسمح لكافة المجالات:

      Access-Control-Allow-Origin: *


باستخدام React و Axios ، ضم رابط الوكيل إلى عنوان URL وأضف العنوان كما هو موضح أدناه

https://cors-anywhere.herokuapp.com/ + Your API URL

فقط عن طريق إضافة رابط البروكسي سيعمل ، ولكن يمكن أن يؤدي أيضًا إلى حدوث خطأ في No Access مرة أخرى. وبالتالي من الأفضل إضافة رأس كما هو موضح أدناه.

axios.get(`https://cors-anywhere.herokuapp.com/[YOUR_API_URL]`,{headers: {'Access-Control-Allow-Origin': '*'}})
      .then(response => console.log(response:data);
  }

في Python ، أستخدم مكتبة Flask-CORS بنجاح كبير. يجعل التعامل مع CORS من السهل جدا وغير مؤلم. أضفت بعض التعليمات البرمجية من وثائق المكتبة أدناه.

تركيب:

$ pip install -U flask-cors

مثال بسيط يسمح لـ CORS لجميع النطاقات على جميع المسارات:

from flask import Flask
from flask_cors import CORS

app = Flask(__name__)
CORS(app)

@app.route("/")
def helloWorld():
  return "Hello, cross-origin-world!"

لمزيد من الأمثلة المحددة ، راجع الوثائق. لقد استخدمت المثال البسيط أعلاه للتغلب على مشكلة CORS في تطبيق أيوني أقوم ببنائه للوصول إلى خادم دورق منفصل.


لمشاركة الأصل العرضي ، عيِّن الرأس: 'Access-Control-Allow-Origin':'*';

Php: header('Access-Control-Allow-Origin':'*');

العقدة: app.use('Access-Control-Allow-Origin':'*');

سيسمح هذا بمشاركة المحتوى الخاص بنطاق مختلف.


Access-Control-Allow-Origin هو رأس CORS (مشاركة مصادر مشتركة) .

عندما يحاول الموقع "أ" جلب محتوى من الموقع "ب" ، يمكن لموقع "ب" إرسال عنوان استجابة " Access-Control-Allow-Origin لإخبار المتصفح بأن محتوى هذه الصفحة يمكن الوصول إلى بعض الأصول. ( الأصل هو نطاق ، بالإضافة إلى رقم المخطط والمنفذ .) افتراضيًا ، لا يمكن الوصول إلى صفحات الموقع ب لأي مصدر آخر ؛ باستخدام رأس Access-Control-Allow-Origin يفتح الباب للوصول عبر الأصل من خلال أصول الطلب المحددة.

بالنسبة إلى كل مورد / صفحة يريد الموقع B إتاحتها للوصول إلى الموقع "أ" ، يجب أن يعرض الموقع "ب" صفحاته مع عنوان الرد:

Access-Control-Allow-Origin: http://siteA.com

لن تحظر المتصفحات الحديثة طلبات عبر النطاقات تمامًا. إذا كان الموقع أ يطلب صفحة من الموقع ب ، فسيقوم المتصفح فعليًا بجلب الصفحة المطلوبة على مستوى الشبكة والتحقق مما إذا كانت عناوين الاستجابة سترى الموقع أ كنطاق مقدم طلب مسموح به. إذا لم يشر الموقع ب إلى أن الموقع أ مسموح له بالوصول إلى هذه الصفحة ، فإن المتصفح سيشغل حدث error في XMLHttpRequest بيانات الاستجابة إلى شفرة جافا سكريبت المطلوبة.

طلبات غير بسيطة

ما يحدث على مستوى الشبكة يمكن أن يكون أكثر تعقيدًا قليلاً مما تم شرحه أعلاه. إذا كان الطلب عبارة عن طلب "غير بسيط" ، فإن المتصفح يرسل أولاً طلب OPTIONS "اختبار مبدئي" بدون بيانات ، للتحقق من أن الخادم سيقبل الطلب. الطلب غير بسيط عندما (أو كلاهما):

  • باستخدام فعل HTTP غير GET أو POST (مثل PUT و DELETE)
  • باستخدام رؤوس طلبات غير بسيطة ؛ رؤوس الطلبات البسيطة الوحيدة هي:
    • Accept
    • Accept-Language
    • Content-Language
    • Content-Type (يكون هذا بسيطًا فقط عندما تكون قيمته هي application/x-www-form-urlencoded أو multipart/form-data أو text/plain )

إذا استجاب الخادم للاختبار المبدئي OPTIONS مع رؤوس الاستجابة المناسبة ( Access-Control-Allow-Headers للرؤوس غير البسيطة ، Access-Control-Allow-Methods للأفعال غير البسيطة) التي تتطابق مع الفعل غير البسيط و / أو غير - رؤوس بسيطة ، ثم يرسل المتصفح الطلب الفعلي.

لنفترض أن الموقع أ يريد إرسال طلب PUT /somePage ، مع قيمة Content-Type غير البسيط application/json ، application/json المتصفح أولاً بإرسال طلب application/json مبدئي:

OPTIONS /somePage HTTP/1.1
Origin: http://siteA.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: Content-Type

لاحظ أنه يتم إضافة Access-Control-Request-Method و Access-Control-Request-Headers بواسطة المستعرض تلقائيًا ؛ لا تحتاج إلى إضافتها. يحقق هذا الاختبار المبدئي OPTIONS رؤوس الاستجابة الناجحة:

Access-Control-Allow-Origin: http://siteA.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: Content-Type

عند إرسال الطلب الفعلي (بعد إجراء الاختبار المبدئي) ، يكون السلوك مطابقًا لكيفية التعامل مع طلب بسيط. وبعبارة أخرى ، يتم التعامل مع طلب غير بسيط يتم بنجاح تنفيذ الاختبار المبدئي الخاص به كطلب بسيط (على سبيل المثال ، يجب أن يرسل الخادم Access-Control-Allow-Origin مرة أخرى للاستجابة الفعلية).

ترسل المتصفحات الطلب الفعلي:

PUT /somePage HTTP/1.1
Origin: http://siteA.com
Content-Type: application/json

{ "myRequestContent": "JSON is so great" }

ويرسل الخادم مرة أخرى Access-Control-Allow-Origin ، تمامًا كما هو الحال في طلب بسيط:

Access-Control-Allow-Origin: http://siteA.com

راجع فهم XMLHttpRequest عبر CORS للحصول على مزيد من المعلومات حول الطلبات غير البسيطة.


1. يقوم عميل بتحميل كود جافا سكريبت MyCode.js من http: // siteA - المصدر.

الرمز الذي يقوم بتنزيله - العلامة النصية html الخاصة بك أو xhr من javascript أو أيا كان - جاء من ، لنقل ، http: // siteZ . وعندما يطلب المتصفح MyCode.js ، يرسل "أصل: رأس" يقول "Origin: http: // siteZ " ، لأنه يمكن أن يرى أنك تطلب الموقع a و siteZ! = siteA. (لا يمكنك التوقف أو التداخل مع هذا.)

2. يحتوي رأس استجابة MyCode.js على Access-Control-Allow-Origin: http: // siteB ، والذي اعتقدت أنه قد تم السماح لـ MyCode.js بعمل مراجع عبر أصل لموقع B.

لا. هذا يعني أنه يُسمح فقط لموقع siteB بتنفيذ هذا الطلب. لذلك ، يحصل طلب MyCode.js من siteZ على خطأ بدلاً من ذلك ، ولا يمنحك المتصفح شيئًا. ولكن إذا قمت بإرجاع خادمك ACAO: siteZ بدلاً من ذلك ، فستحصل على MyCode.js. أو إذا كان يرسل "*" ، فسيعمل ذلك ، الذي سيسمح للجميع بالدخول. أو إذا كان الخادم يرسل دائمًا السلسلة من أصل: رأس ... لكن ... للأمان ، إذا كنت خائفًا من المتسللين ، يجب على الخادم الخاص بك السماح فقط للأصول في قائمة مختصرة ، التي يسمح لها بتقديم تلك الطلبات.

ثم ، يأتي MyCode.js من siteA. عند تقديم طلبات إلى siteB ، فهي كلها مشتركة ، ويرسل المتصفح الأصل: siteA ، و siteB يجب أن يأخذ الموقع A ، ويتعرف على القائمة المختصرة من الطالبين المسموح به ، ويرسل مرة أخرى ACAO: siteA. عندئذ فقط سيسمح المستعرض للنص البرمجي بالحصول على نتائج تلك الطلبات.





cors