javascript - resource - same origin policy شرح




خطأ XmlHttpRequest: غير مسموح المنشأ فارغ بواسطة Access-Control-Allow-Origin (11)

أعمل على تطوير صفحة تسحب الصور من Flickr و Panoramio عبر دعم AJAX من jQuery.

يعمل الجانب Flickr بشكل جيد ، ولكن عندما أحاول $.get(url, callback) من Panoramio ، أرى خطأ في وحدة تحكم Chrome:

لا يمكن لـ XMLHttpRequest تحميل http://www.panoramio.com/wapi/data/get_photos?v=1&key=dummykey&tag=test&offset=0&length=20&callback=processImages&minx=-30&miny=0&maxx=0&maxy=150 . لا يسمح لاغية المنشأ عن طريق التحكم بالوصول - السماح - المنشأ.

إذا استفسرت عن عنوان URL هذا من متصفح مباشر ، فستعمل بشكل جيد. ما الذي يجري ، وهل يمكنني الالتفاف حول هذا؟ هل أقوم بإنشاء استعلامي بشكل غير صحيح ، أم أن هذا شيء تفعله Panoramio لإعاقة ما أحاول القيام به؟

لم يحضر Google أي مطابقات مفيدة في رسالة الخطأ .

تصحيح

إليك بعض نماذج التعليمة البرمجية التي توضح المشكلة:

$().ready(function () {
  var url = 'http://www.panoramio.com/wapi/data/get_photos?v=1&key=dummykey&tag=test&offset=0&length=20&callback=processImages&minx=-30&miny=0&maxx=0&maxy=150';

  $.get(url, function (jsonp) {
    var processImages = function (data) {
      alert('ok');
    };

    eval(jsonp);
  });
});

يمكنك تشغيل المثال عبر الإنترنت .

تحرير 2

شكرا لدارين لمساعدته في هذا. الكود أعلاه غير صحيح. استخدم هذا بدلاً من ذلك:

$().ready(function () {
  var url = 'http://www.panoramio.com/wapi/data/get_photos?v=1&key=dummykey&tag=test&offset=0&length=20&minx=-30&miny=0&maxx=0&maxy=150&callback=?';

  $.get(url, function (data) {
    // can use 'data' in here...
  });
});

أستخدم خادم Apache ، لذلك استخدمت وحدة mod_proxy. تمكين الوحدات:

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so

ثم أضف:

ProxyPass /your-proxy-url/ http://service-url:serviceport/

أخيرًا ، قم بتمرير proxy-url إلى البرنامج النصي الخاص بك.


إذا كنت تجري اختبارًا محليًا أو تتصل بالملف من شيء مثل file:// فأنت بحاجة إلى تعطيل أمان المتصفح.

على MAC: open -a Google\ Chrome --args --disable-web-security


الناس،

واجهت مشكلة مماثلة. ولكن باستخدام Fiddler ، تمكنت من الحصول على هذه المسألة. تكمن المشكلة في أن عنوان URL الخاص بالعميل الذي تم تكوينه في تطبيق CORS على جانب واجهة برمجة تطبيقات الويب لا يجب أن يحتوي على شرطة مائلة للأمام. بعد إرسال طلبك عبر Google Chrome وفحص علامة التبويب TextView في قسم الرؤوس في Fiddler ، تنص رسالة الخطأ على شيء كالتالي:

* "أصل السياسة المحدد your_client_url: /" غير صالح. لا يمكن أن ينتهي بشرطة مائلة للأمام. "

هذا هو ملتوي حقيقي لأنه يعمل دون أي مشاكل على إنترنت إكسبلورر ، ولكن أعطاني صداع عند الاختبار باستخدام جوجل كروم.

أزلت شرطة مائلة للأمام في رمز CORS وأعدت واجهة برمجة تطبيقات الويب ، والآن أصبحت واجهة برمجة التطبيقات متاحة عبر Chrome و Internet Explorer بدون أي مشكلات. يرجى إعطاء هذه اللقطة.

شكرا ، آندي


تأكد من أنك تستخدم أحدث إصدار من JQuery. كنا نواجه هذا الخطأ لـ JQuery 1.10.2 و تم حل الخطأ بعد استخدام JQuery 1.11.1


في حالتي ، عملت الشفرة نفسها بشكل جيد على Firefox ، ولكن ليس على Google Chrome. قالت وحدة تحكم جافا سكريبت في Google Chrome:

XMLHttpRequest cannot load http://www.xyz.com/getZipInfo.php?zip=11234. 
Origin http://xyz.com is not allowed by Access-Control-Allow-Origin.
Refused to get unsafe header "X-JSON"

اضطررت لإسقاط جزء www من عنوان Ajax URL لكي يتطابق بشكل صحيح مع عنوان URL الأصلي وعمل جيدًا بعد ذلك.


قد تحتاج إلى إضافة HEADER في برنامجك النصي المسمى ، هنا ما كان يجب عليّ فعله في PHP:

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

مزيد من التفاصيل في مجال AJAX عبر خدمات oub (باللغة الفرنسية).


كملاحظة أخيرة فإن وثائق Mozilla تقول صراحة بذلك

يفشل المثال أعلاه إذا تم ترميز العنوان كـ: Access-Control-Allow-Origin: *. بما أن Access-Control-Allow-Origin يذكر بشكل صريح http: //foo.example ، يتم إرجاع المحتوى المعرفي - المعرفي إلى محتوى الويب الاستنادي.

ونتيجة لذلك ، ليست مجرد ممارسة سيئة لاستخدام "*". ببساطة لا يعمل :)


لا تدعم جميع الخوادم jsonp. يتطلب من الخادم ضبط وظيفة رد الاتصال في نتائجها. يمكنني استخدام هذا للحصول على ردود json من المواقع التي ترجع إلى json خالص ولكن لا تدعم jsonp:

function AjaxFeed(){

    return $.ajax({
        url:            'http://somesite.com/somejsonfile.php',
        data:           {something: true},
        dataType:       'jsonp',

        /* Very important */
        contentType:    'application/json',
    });
}

function GetData() {
    AjaxFeed()

    /* Everything worked okay. Hooray */
    .done(function(data){
        return data;
    })

    /* Okay jQuery is stupid manually fix things */
    .fail(function(jqXHR) {

        /* Build HTML and update */
        var data = jQuery.parseJSON(jqXHR.responseText);

        return data;
    });
}

للتسجيل ، بقدر ما أستطيع أن أقول ، كان لديك مشكلتين:

  1. لم يتم تمرير محدد نوع "jsonp" إلى $.get الخاص بك ، لذلك تم استخدام XMLHttpRequest عادي. على الرغم من ذلك ، يدعم المستعرض الخاص بك CORS (مشاركة مصادر عبر مشتركة) للسماح بـ XMLHttpRequest عبر المجال إذا كان الملقم "موافق" عليه. هذا هو المكان الذي جاء فيه رأس Access-Control-Allow-Origin .

  2. أعتقد أنك ذكرت أنك كنت تشغلها من ملف: // URL. هناك طريقتان لرؤوس CORS للإشارة إلى أن XHR عبر المجال هو موافق. أحدها إرسال Access-Control-Allow-Origin: * (التي إذا كنت تصل إلى Flickr عبر $.get ، يجب أن يكونوا قد قاموا بذلك) بينما الآخر كان $.get صدى محتويات رأس Origin . ومع ذلك ، ينتج عن file:// عناوين URL أصلًا لا يمكن تخويله عبر إعادة الصدى.

تم حل $.getJSON الأولى بطريقة دائرية بواسطة اقتراح دارين لاستخدام $.getJSON . يفعل القليل من السحر لتغيير نوع الطلب من الافتراضي "json" إلى "jsonp" إذا رأى الاستدعاء الفرعي callback=? في عنوان URL.

الذي حل الثاني من خلال عدم محاولة تنفيذ طلب CORS من file:// URL.

للتوضيح لأشخاص آخرين ، فيما يلي إرشادات تحري الخلل وإصلاحه البسيطة:

  1. إذا كنت تحاول استخدام JSONP ، فتأكد من وجود أحد الأمور التالية:
    • أنت تستخدم $.get وتعيين dataType إلى jsonp .
    • أنت تستخدم $.getJSON وتضمّن callback=? في عنوان URL.
  2. إذا كنت تحاول إجراء XMLHttpRequest عبر المجال عبر CORS ...
    1. تأكد من اختبارك عبر http:// . تحتوي النصوص البرمجية التي يتم تشغيلها عبر file:// على دعم محدود لـ CORS.
    2. تأكد من أن المتصفح يدعم CORS بالفعل . (تأخرت Opera و Internet Explorer إلى الحفلة)

لمشروع HTML بسيط:

cd project
python -m SimpleHTTPServer 8000

ثم استعرض ملفك.


يعمل لي على Google Chrome v5.0.375.127 (أحصل على التنبيه):

$.get('http://www.panoramio.com/wapi/data/get_photos?v=1&key=dummykey&tag=test&offset=0&length=20&callback=?&minx=-30&miny=0&maxx=0&maxy=150',
function(json) {
    alert(json.photos[1].photoUrl);
});

كما $.getJSON() باستخدام طريقة $.getJSON() بدلاً من أن الطريقة السابقة لا تعمل على IE8 (على الأقل على جهازي):

$.getJSON('http://www.panoramio.com/wapi/data/get_photos?v=1&key=dummykey&tag=test&offset=0&length=20&callback=?&minx=-30&miny=0&maxx=0&maxy=150', 
function(json) {
    alert(json.photos[1].photoUrl);
});

يمكنك تجربتها عبر الإنترنت من هنا .

تحديث:

الآن بعد أن أظهرت شفرتك ، يمكنني رؤية المشكلة بها. كنت تواجه كل من وظيفة مجهولة ووظيفة مضمنة ولكن كلاهما processImages . هذه هي الطريقة التي يعمل بها jQuery's JSONP support. لاحظ كيف أقوم بتعريف callback=? بحيث يمكنك استخدام وظيفة مجهولة. يمكنك قراءة المزيد $.getJSON() .

ملاحظة أخرى هي أنه لا يجب عليك الاتصال بشركة eval. سيتم بالفعل تحليل المعلمة التي تم تمريرها إلى الدالة المجهولة إلى JSON بواسطة jQuery.







jsonp