Socket.io: أخطاء CORS بعد التحديث إلى 2.2.0

تم إنشاؤها على ٢٩ نوفمبر ٢٠١٨  ·  36تعليقات  ·  مصدر: socketio/socket.io

اتريد:

  • [x] أبلغ عن خطأ
  • [] طلب ميزة

السلوك الحالي

الحصول على الكثير من أخطاء CORS بعد التحديث الأخير.
screen shot 2018-11-29 at 1 13 25 pm

خطوات إعادة الإنتاج (إذا كان السلوك الحالي خطأ)

الريبو . انظر README للحصول على التعليمات.

سلوك متوقع

لا توجد أخطاء CORS.

يثبت

  • نظام التشغيل: Mac
  • المتصفح: Chrome 70
  • الإصدار socket.io: 2.2.0

معلومات أخرى (مثل stacktraces والمشكلات ذات الصلة واقتراحات كيفية الإصلاح)

أدلى davericher بتعليق هنا يشير إلى ذلك. ربما لديه المزيد من التفاصيل.

التعليق الأكثر فائدة

الحل: npm تثبيت المقبس. [email protected]

ال 36 كومينتر

+1 بدأت بالفشل منذ أن قمت بتنزيل الحزم مرة أخرى.

الحل: npm تثبيت المقبس. [email protected]

الشيء المضحك هو أنني أستخدم رد اتصال أصول مخصصة ويعيد "*" كأصل مسموح به بدلاً من الأصل الفعلي الذي تم تمريره من العميل عندما يتم استدعاء رد الاتصال مع ضبط النجاح على صحيح.
في 2.1 تم استخدامه لإرجاع رأس الأصل الذي تم تمريره من العميل.

حسنًا .. لا أرى أي شيء متعلق بسجل التغيير ... قد يكون تحديث الحزمة ws .

هل يستطيع أي شخص إعادة إنتاج المشكلة؟

نعم. يجب أن يكون لديك خادم مقبس في مجال منفصل.

darrachequesne : لقد قمت بتحديث إظهار المشكلة. التعليمات موجودة في README في الريبو.

طريقة أخرى لحل المشكلة: املأ خاصية origin في تكوين خادم socketio الخاص بك:

const Server = require('socket.io');
const io = new Server({
  origins: 'http://your-cors-url' // i believe can also be an array of urls, defaults to '*'
});

يجب أن ترى هذا يظهر في رؤوس الاستجابة لطلب المصافحة في علامة تبويب الشبكة:
screen shot 2018-11-29 at 4 10 28 pm

يجب أن يتوقف المتصفح عن الشكوى بشأن انتهاك CORS بعد ذلك.

darrachequesne يبدو أنك إذا قمت بالتعليق على هذه الأسطر بـ engine.io-client :

if ('withCredentials' in xhr) {
  xhr.withCredentials = true;
}

ثم تنجح الطلبات.

لذا ربما ، في الإصدار <2.2.0 ، بطريقة ما 'withCredentials' in xhr === false ؟

@ sjones6 شكرا على الريبو. ما لا أفهمه هو أن المثال الخاص بك هو حالة CORS أساسية ، حيث يتم تقديم العميل من موقع ( localhost:3001 ) يختلف عن الخادم ( localhost:3000 ). لا ينبغي أن يعمل ذلك في الإصدارات السابقة أيضًا ، ويتم حله باستخدام المعلمة origins ، كما أشرت.

أعتقد أنه مع أوراق الاعتماد تم ضبطه دائمًا على الحقيقة.

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

https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS/Errors/CORSNotSupportingCredentials

flenter هل يمكن أن يكون مرتبطًا بـ https://github.com/socketio/engine.io/pull/511؟

خيار آخر هو بالطبع ضبط بيانات الاعتماد على false ، ولكن هذا يعني أن خادم socket io لا يهتم بالحصول على / تعيين أي ملفات تعريف ارتباط. لست متأكدًا مما إذا كان هذا هو الحال مع المقبس io

https://github.com/socketio/engine.io/pull/511/files#diff -c945a46d13b34fcaff544d966cffcabaL259

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

في كلتا الحالتين ، بعد ذلك العلاقات العامة ، هذا تغيير جذري على الرغم من أنني أعتقد؟

كما هو الحال الآن ، لا أرى أي طريقة لدعم جميع الأصول عندما تكون بيانات الاعتماد مضبوطة على "صواب"

لقد عدت إلى العلاقات العامة ونشرت إصدارًا جديدًا من engine.io . هل يمكنك التحقق من أنه يعمل على حل المشكلة؟ https://github.com/socketio/engine.io/commits/master

أو لتجنب حدوث تغيير فاصل ، فعندما لا يتم تعيين الأصول بشكل صريح في الخيارات / التعيين إلى غير محدد (افتراضي) أو يتم استدعاء وظيفة الأصول بـ غير محدد ، فسيتم استخدام رأس أصل العميل (السلوك الافتراضي القديم)

ألن يكون من المنطقي إيقاف تشغيل بيانات الاعتماد بشكل افتراضي؟ بالنسبة لمعظم الحالات لا ينبغي أن يكون على أي حال ، أليس كذلك؟

darrachequesne : شكرا ؛ لقد سحبنا 3.3.2 من engine.io وعادت الأشياء إلى بيئاتنا.

وبناء على هذا التعليق هذا التعليق منxaviergonz، أعتقد أن لدينا صورة أكثر وضوحا:

في socket.io <2.2 ، تم فرض CORS _ فقط إذا _ قدمت origins ؛ إذا لم يكن الأمر كذلك ، فقد تم السماح بجميع الأصول. في 2.2.0 (إدارة جديدة حقًا على [email protected] عبر هذا الالتزام على ما أعتقد) ، يتم فرض CORS سواء قمت بتوفير خيارات origins .

أنا جميعًا أقوم بفرض CORS كسلوك افتراضي ... ولكن يبدو أنه من المحتمل أن يكون هذا تغييرًا جذريًا يجب إضافته في الإصدار الرئيسي الجديد.


أحدث تعديل لتصحيح رقم الإصدار الخاطئ من engine.io.

هل هناك أي وقت متوقع للوصول إلى إصدار إصلاح الأخطاء؟ يستخدم 2.2.0 محرك 3.3.1 وليس 3.3.2

neemah اضطررت إلى إزالة وإضافة socket.io للحصول على الإصدار المحدث:
إزالة الغزل socket.io && الغزل إضافة socket.io

هنا قائمة الغزل الخاصة بي الآن:
├─ مقبس. [email protected]
│ ├─ debug@~4.1.0
│ ├─ [email protected]
│ │ └─ ms^ 2.1.1
│ ├─ engine.io@~3.3.1
│ has-binary2@~1.0.2
│ ├─ [email protected]
│ ├─ socket.io-adapter@~1.1.0
│ ├─ مقبس. [email protected]
│ └─ socket.io-parser@~3.3.0

حسنًا @ ravid87 ،

neemah كان المكسور 3.2.2

darrachequesne : شكرا ؛ لقد سحبنا 3.2.2 من engine.io وعادت الأشياء إلى بيئاتنا.

وبناء على هذا التعليق هذا التعليق منxaviergonz، أعتقد أن لدينا صورة أكثر وضوحا:

في socket.io <2.2 ، تم فرض CORS _ فقط إذا _ قدمت origins ؛ إذا لم يكن الأمر كذلك ، فقد تم السماح بجميع الأصول. في 2.2.0 (إدارة جديدة حقًا على [email protected] عبر هذا الالتزام على ما أعتقد) ، يتم فرض CORS سواء قمت بتوفير خيارات origins .

أنا جميعًا أقوم بفرض CORS كسلوك افتراضي ... ولكن يبدو أنه من المحتمل أن يكون هذا تغييرًا جذريًا يجب إضافته في الإصدار الرئيسي الجديد.

@ ravid87 3.2.2 غير موجود https://github.com/socketio/engine.io/tree/3.2.2 ، لذلك أفترض أن مؤلف الرسالة يعني 3.3.2 ، وهو أحدث إصدار ، إذا قمت بفحص الالتزامات / العلامات.

لذلك ما زلت في انتظار الإصلاح :)

neemah @ ravid87 : آسف للارتباك ؛ تصحيح الخطأ المطبعي عن طريق تحرير التعليق ...

neemah : npm يجب أن يتم حله بشكل صحيح إلى [email protected] بناءً على الأقسام في socket.io :

"engine.io": "~3.3.1"

تحتاج إلى حذف package-lock.json (أو yarn.lock) أولاً على الرغم من أنه قبل التثبيت ستحصل على 3.3.1 مرة أخرى ..

@ sjones6 طيب تشك لتصحيح النسخة. لكنني ما زلت في حيرة من أمري لأنني
1) حتى إذا قمت بحذف yarn.lock ، لدي هذا في yarn.lock الخاص بي بعد تثبيت نظيف (yarn remove socket.io ، yarn clean cache ، yarn add socket.io):

socket.io^2.2.0:
الإصدار "2.2.0"
تم حلها " https://registry.yarnpkg.com/socket.io/-/socket.io-2.2.0.tgz#f0f633161ef6712c972b307598ecd08c9b1b4d5b "
النزاهة sha512-wxXrIuZ8AILcn + f1B4ez4hJTPG24iNgxBBDaJfT6MsyOhVYiTXWexGoPkd87ktJG8kQEcL / NBvRi64 + 9k4Kc0w ==
التبعيات:
تصحيح "~ 4.1.0"
engine.io "~ 3.3.1"
has-binary2 "~ 1.0.2"
socket.io- محول "~ 1.1.0"
عميل socket.io "2.2.0"
socket.io-parser "~ 3.3.0"

2) لا أفهم لماذا يعمل كل شيء مع 3.3.1 ...

2 - ربما لأنك تقوم بالتدقيق على نفس المجال حيث لا تظهر هذه المشكلة

neemah هنا الإعداد الخاص بي:
-> يتم تقديم تطبيق رد الفعل من foobar.com
-> المقبس موجود على socket.foobar.net

لذلك ليس على نفس المجال: /

فمن المحتمل أنك قمت بتكوين الأصل بقيمة http[s]://foobar.com حيث تقوم بتشغيل socket.foobar.net

neemah لم يتم تكوين أصول على socket.io أو express.js.

عانيت من مشكلة CORS بالأمس واليوم بعد تثبيت نظيف لـ socket.io كل شيء يعمل مرة أخرى ...

@ ravid87 : هل يمكنك التأكيد اليوم أن لديك [email protected] في نظام الملفات الخاص بك اليوم؟ بناءً على تعليقك ، فإن التبعية على engine.io "~3.3.1" صحيحة ولكن النسخة التي تم تنزيلها يجب أن تكون 3.3.2 وليس 3.3.1 . بالأمس ، كان من الممكن أن يكون 3.3.1 حتى يتم نشر التحديث.

يجب أن يخبرك yarn list --pattern engine.io --depth=5 .

@ sjones6 نعم! لدي 3.3.2: +1: thx للتوضيح :)

لدي نفس المشكلة مع CORS:

-- [email protected] - محرك. [email protected]

أواجه نفس المشكلة التي استجابت

سياق الخطأ الكامل:

إصدارات جانب الخادم:

    "socket.io": "^2.3.0",
    "engine.io": {
      "version": "3.4.0"

إصدارات جانب العميل:

    <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.3.0/socket.io.js"></script>
  1. العميل عند: http://localhost:5530/
    رمز العميل:
      // ... get sessionToken, initialize stuff.

      var socket = io.connect('http://localhost:8011', {
        query: query,
        transportOptions: {
          polling: {
            extraHeaders: {
              'x-user-token': sessionToken
            }
          }
        }
      });

      socket.on('connect', () => {
        console.log("===> rootNspDemo connection established!!!!!, socket: ", socket.id);
      })
      socket.on('disconnect', (reason) => {
        console.log('rootNspDemo connection disconnected: ' + reason);
        socket.close(); // stop reconnecting
      })
      socket.on(topic, function(data) {
          console.log("###> root namespace progress data: ", data);
          document.getElementById("taskStatus").innerHTML = data.taskStatus;
      });
    }

جانب الخادم:

// ... imports


// Initialize express
const app = express();

// TRIED ALL THESE, BUT NONE WORK
// const cors = require('cors');
// app.use(cors({credentials: true, methods: ['GET', 'PUT', 'POST', 'PATCH', 'DELETE', 'OPTIONS']}));
// app.options('*', cors({credentials: true, methods: ['GET', 'PUT', 'POST', 'PATCH', 'DELETE', 'OPTIONS']}));
// app.use(cors());
// app.options('*', cors({methods: ['GET', 'PUT', 'POST', 'PATCH', 'DELETE', 'OPTIONS']}));

const server = app.listen(SERVER_PORT, () => {
    logInfo(
      `%s v%s listening on port %s in %s mode`,
      PKG.name,
      PKG.version,
      SERVER_PORT,
      ENV
    );
  });


// var socketIOAllowedOrigins = "http://localhost:* http://127.0.0.1:*";
var socketIOAllowedOrigins = "http://localhost:5530";

// TRIED THIS ALSO, DIDN'T WORK
// const io = require('socket.io').listen(server, {origins: socketIOAllowedOrigins});

const socketIOAuth = async function(socket, next) {
  const sessionToken = socket.handshake.headers['x-user-token'];
  const user = await getUser(sessionToken);
  if (!user) {
  // eslint-disable-next-line no-console
    console.log('---> socket ' + socket.id + ' of nsp: ' + socket.nsp.name + ' FAILED authentication !!');
    socket.disconnect('unauthorized');
    next(new Error('invalid sessionToken'));
  } else {
  // eslint-disable-next-line no-console
    console.log('---> socket ' + socket.id + ' of nsp: ' + socket.nsp.name + ' is authenticated!!');
  }

  return next();
};

const io = require('socket.io').listen(server);
io.use(socketIOAuth); // REMOVING THIS, and NOT SENDING AUTH TOKEN FROM CLIENT, THEN IT WORKS
// io.origins('*');

io.origins(['localhost:8011', 'localhost:5530',
  'http://localhost:8011', 'http://localhost:5530']);

const runDemo = (socket) => {
    // Demo test of progress bar
    // eslint-disable-next-line no-console
    console.log('Running socket.io demo for topic: ', socket.handshake.query.topic);
    let i = 0;
    const interval = setInterval(function() {
      if (i < 100) {
        socket.emit(socket.handshake.query.topic, { rootDummy: true, progress: i, taskStatus: 'RUNNING' });
        i++;
      } else {
        socket.emit(socket.handshake.query.topic, { rootDummy: true, progress: i, taskStatus: 'SUCCESS' });
        clearInterval(interval);
      }
    }, 1000);
  }

io.on('connection', runDemo);

إليك الأجزاء المثيرة للاهتمام التي قمت بتصحيحها:

إزالة برمجية المصادقة الوسيطة من socketio في جانب الخادم - io.use(socketIOAuth); وأيضًا إزالة مرور SessionToken من جانب العميل:

        transportOptions: {
          withCredentials: true,
          polling: {
            extraHeaders: {
              // 'x-user-token': sessionToken
            }
          }
        }

يجعل الاتصال يعمل بشكل جيد.

يمكنني رؤية سجل الأخطاء في nginx على النحو التالي:

"06/Feb/2020:21:36:44 +0530" client=127.0.0.1 method=OPTIONS request="OPTIONS /socket.io/?topic=rootNspDemo&demo=true&EIO=3&transport=polling&t=N0RGEpG HTTP/1.1" request_length=574 status=400 bytes_sent=326 body_bytes_sent=54 referer=http://localhost:5530/ user_agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36" upstream_addr=127.0.0.1:8011 upstream_status=400 request_time=0.005 upstream_response_time=0.004 upstream_connect_time=0.000 upstream_header_time=0.000

يعطيني curl:

 curl -XOPTIONS 'http://local-messaging.onupkeep.com/socket.io/?topic=rootNspDemo&demo=true&EIO=3&transport=polling&t=N0RNF8q' -H 'Accept: */*' -H 'x-user-token: r:b33a941138a226f0fd37a9ea51c24c16' -H 'Referer: http://localhost:5530/' -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36' --compressed
{"code":2,"message":"Bad handshake method"}

وهو متوافق مع الشرح هنا: https://stackoverflow.com/a/52048304/11626829

يقوم المستعرض بشكل أساسي بإرسال طلب الخيارات قبل الرحلة ، ولكن يتم تناول ذلك بواسطة socket.io كطلب مصافحة.

لدي نفس المشكلة ..

const options = { transportOptions: { polling: { extraHeaders: { 'x-auth-token': accessToken }, }, } }; socket = socketIOClient(config.socketUrl, options);

يعمل بشكل جيد عندما أرسله مع معلمات الاستعلام:

const options = { query:{ auth_token: accessToken } }; socket = socketIOClient(config.socketUrl, options);

لدي نفس المشكلة ..

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات

القضايا ذات الصلة

doughsay picture doughsay  ·  4تعليقات

dmuth picture dmuth  ·  3تعليقات

Elliot9 picture Elliot9  ·  4تعليقات

gCurtisCT picture gCurtisCT  ·  4تعليقات

varHarrie picture varHarrie  ·  3تعليقات