خطأ XMLHTTPREQUEST: لا يُسمح بالأصل الفارغ عن طريق إمكانية الوصول إلى الأصول

StackOverflow https://stackoverflow.com/questions/3595515

سؤال

أقوم بتطوير صفحة تسحب الصور من Flickr و Panoramio عبر دعم Ajquery من 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 من المتصفح مباشرة ، فهو يعمل بشكل جيد. ما الذي يحدث ، وهل يمكنني الالتفاف على هذا؟ هل أقوم بتأليف استعلامي بشكل غير صحيح ، أم أن هذا شيء يفعله بانوراميو لعياق ما أحاول القيام به؟

لم تطرح 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...
  });
});
هل كانت مفيدة؟

المحلول

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

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

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

تم حل الأول بطريقة دورية من خلال اقتراح دارين للاستخدام $.getJSON. إنه يقوم بسحر صغير لتغيير نوع الطلب من الافتراضي لـ "JSON" إلى "JSONP" إذا رأى السلسلة الفرعية callback=? في عنوان URL.

التي حلت الثانية بعد لم تعد تحاول إجراء طلب CORS من أ file:// عنوان URL.

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

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

نصائح أخرى

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

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

مزيد من التفاصيل في Cross Domain Ajax OU Services Web Web (بالفرنسية).

لمشروع 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() الطريقة بدلاً من ذلك لأن السابق لا يعمل على 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. هذه هي الطريقة التي يعمل بها دعم JSORY's JSONP. لاحظ كيف أقوم بتحديد callback=? بحيث يمكنك استخدام وظيفة مجهولة. يمكنك قراءة المزيد عن ذلك في الوثائق.

ملاحظة أخرى هي أنه يجب ألا تسمي Eval. سيتم بالفعل تحليل المعلمة التي تم تمريرها إلى وظيفتك المجهولة في JSON بواسطة JQuery.

طالما أن الخادم المطلوب يدعم تنسيق بيانات JSON ، استخدم واجهة JSONP (JSON PADDING). يسمح لك بتقديم طلبات مجال خارجية بدون خوادم وكيل أو مواد رأس فاخرة.

انها ال نفس سياسة الأصل, ، يجب عليك استخدام واجهة JSON-P أو وكيل يعمل على نفس المضيف.

تمكنا من ذلك عبر http.conf ملف (تم تحريره ثم إعادة تشغيل خدمة HTTP):

<Directory "/home/the directory_where_your_serverside_pages_is">
    Header set Access-Control-Allow-Origin "*"
    AllowOverride all
    Order allow,deny
    Allow from all
</Directory>

في ال Header set Access-Control-Allow-Origin "*", ، يمكنك وضع عنوان URL دقيق.

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

على ماك:open -a Google\ Chrome --args --disable-web-security

في حالتي ، عملت نفس الرمز بشكل جيد على 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 من عنوان URL AJAX حتى يتطابق بشكل صحيح مع عنوان URL الأصل وعمل بشكل جيد في ذلك الوقت.

لا تدعم جميع الخوادم JSONP. يتطلب من الخادم تعيين وظيفة رد الاتصال في نتائجه. أستخدم هذا للحصول على ردود JSON من المواقع التي تعيد Pure 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;
    });
}

أستخدم Apache Server ، لذلك استخدمت وحدة 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 إلى البرنامج النصي الخاص بك.

كما الملاحظة النهائية تقول وثائق موزيلا صراحة الذي - التي

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

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

لقد حصلت أيضًا على نفس الخطأ في Chrome (لم أختبر عوائق أخرى). كان بسبب حقيقة أنني كنت أتنقل على domain.com بدلاً من www.domain.com. غريب بعض الشيء ، لكن يمكنني حل المشكلة عن طريق إضافة الأسطر التالية إلى .htaccess. يعيد توجيه Domain.com إلى www.domain.com وتم حل المشكلة. أنا زائر على شبكة الإنترنت كسول ، لذا لا أكسب WWW تقريبًا ولكن يبدو أنه في بعض الحالات مطلوب.

RewriteEngine on
RewriteCond %{HTTP_HOST} ^domain\.com$ [NC]
RewriteRule ^(.*)$ http://www.domain.com/$1 [R=301,L]

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

يا قوم،

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

*"السياسة المحددة أصل your_client_url:/'غير صالح. لا يمكن أن تنتهي بقطع إلى الأمام ".

هذا أمر غريب حقيقي لأنه نجح دون أي مشاكل في Internet Explorer ، لكنه أعطاني صداعًا عند الاختبار باستخدام Google Chrome.

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

شكرا ، آندي

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

لذلك البحث قليلا ، وجدت هذا ليستخدم:

sudo npm -g install simple-http-server # to install
nserver # to use

وبعد ذلك سوف يخدم في http://localhost:8000.

ل PHP - هذا العمل بالنسبة لي على Chrome و Safari و Firefox

https://w3c.github.io/webappsec-cors-for-developers/#avoid-renturning-access-control-Ollow-Origin-null

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

باستخدام Axios Call PHP Live Services مع ملف: //

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top