Socket.io-client: Разрешить socket.handshake.query быть функцией

Созданный на 22 мая 2017  ·  9Комментарии  ·  Источник: socketio/socket.io-client

Вы хотите:

  • [x] сообщить об ошибке
  • [] запросить функцию

Текущее поведение

socket.handshake.query настоящее время позволяет устанавливать данные на connect , но не может быть обновлен по ссылке до reconnect . Это вызывает проблемы при авторизации сокет-соединения с помощью токенов обновления.

Действия по воспроизведению (если текущее поведение является ошибкой)

//client
io.connect("wss://socket.server.com", {
   query : {
      token:"something dynamic"
   }
});

Если сервер перезагружен и клиенты reconnect , токен может быть устаревшим при повторной авторизации сокета.

//server
io.use(function(socket, next) {
   var query = socket.handshake.query;
   if(isValidToken(query.token)){
      next();//will never fire if the token has been updated
   }
});

Ожидаемое поведение

Разрешить запросу быть function :

io.connect("wss://socket.server.com", {
   query : function(){
      return {
         token:"something dynamic"
      }
   }
});

Настраивать

  • версия socket.io: 2.0.1

Как исправить

В текущем конструкторе Socket:

if (opts && opts.query) {
   this.query = opts.query;
}

Можно изменить на это:

if(opts && opts.query) {
   this.query = typeof opts.query == 'function' && opts.query.call(this) || opts.query;
}

Самый полезный комментарий

@reeltimedoktor в настоящее время вы должны быть в состоянии обновить query объект на reconnect_attempt события:

socket.on('reconnect_attempt', function () {
  socket.io.opts.query = { token: /* ... */ };
});

Все 9 Комментарий

+1
Исправление ошибки № 1086 также должно решить вашу проблему. Изменение параметров запроса после успешного подключения работало со старой версией socket.io-client, но с текущей версией ссылка на объект запроса теряется :(

@reeltimedoktor в настоящее время вы должны быть в состоянии обновить query объект на reconnect_attempt события:

socket.on('reconnect_attempt', function () {
  socket.io.opts.query = { token: /* ... */ };
});

Решение @darrachequesne, похоже, не работает для меня :(

Я использую socket.io-client version 2.3.0 на клиенте с сервером узла с socket.io version 2.3.0 .

На клиенте делаю так:

 socket.on('reconnect_attempt', async () => {
      const newToken = await getNewToken();
      socket.io.opts.query = {
        token: latestToken,
      };
    });

И затем сервер аутентифицирует токен с помощью промежуточного программного обеспечения, переданного в io.use() (которое затем должно срабатывать при подключении или повторном подключении сокета, ага?).

В настоящий момент аутентификация сервера не работает при повторном подключении, говоря, что срок действия токена истек - похоже, новый токен не назначается должным образом для socket.io.opts.query.token - есть идеи, почему?

Спасибо :)

Обновление: похоже, что в объекте сокета есть множество разных мест, где хранится токен аутентификации, например socket.io.engine.query.token , socket.io.engine.transport.query.token . Они не заполняются автоматически при установке socket.io.opts.query.token . Однако их изменение по-прежнему не влияет на то, что серверы «видят» - он по-прежнему видит только старый токен.

Маркер также, кажется, включен в качестве параметра URL-адреса в некоторые поля URL-адреса в объекте сокета. Возможно, их тоже нужно обновить?

После дальнейшего изучения, кажется , что установка маркеров на socket.io.opts.query.token достаточно , чтобы изменить маркер для повторной аутентификации на повторном подключение - что - то еще , кажется, проблема для моего приложения, возможно , что - то делать с firebase маркеров поколения AUTH. Так что для всех, кто сталкивается с этим, решение @darrachequesne работает!

Хорошо, думаю, я исправил это - вам нужно убедиться, что вы получаете новый токен синхронно в обратном вызове reconnect_attempt, т.е. не делайте этого:

 socket.on('reconnect_attempt', async () => {
      const newToken = await getNewToken(); // won't work
      socket.io.opts.query = {
        token: latestToken,
      };
    });

Похоже, что аутентификация на стороне сервера выполнялась до того, как был установлен новый токен. Если вы получаете токен синхронно (получая его некоторое время назад и сохраняя его, а затем просто получая его в обратном вызове слушателя), сервер получает новый токен аутентификации вовремя для аутентификации повторного подключения.

с "socket.io-client": "3.0.4" я получаю ошибку TS2341: Property 'opts' is private and only accessible within class 'Manager'. . Я использую "typescript": "4.1.3"
image

Хорошо, думаю, я исправил это - вам нужно убедиться, что вы получаете новый токен _синхронно_ в обратном вызове reconnect_attempt, т.е. не делайте этого:

 socket.on('reconnect_attempt', async () => {
      const newToken = await getNewToken(); // won't work
      socket.io.opts.query = {
        token: latestToken,
      };
    });

Похоже, что аутентификация на стороне сервера выполнялась до того, как был установлен новый токен. Если вы получаете токен синхронно (получая его некоторое время назад и сохраняя его, а затем просто получая его в обратном вызове слушателя), сервер получает новый токен аутентификации вовремя для аутентификации повторного подключения.

У нас аналогичная проблема. Но мой текущий обходной путь - disconnect со стороны сервера, когда аутентификация не удалась. после получения события disconnect на клиенте мы повторно конструируем запрос / заголовок с помощью вызова async Promise. К тому времени, когда он достигает события reconnecting , он уже имеет новое значение в запросе / заголовке.

Для будущих читателей:

Поведение параметра query в Socket.IO v2 немного странно, поскольку оно используется в обоих:

  • параметры запроса (для экземпляра Manager)
  • рукопожатие Socket.IO (но только для нестандартного пространства имен)

Так что я не уверен, как это исправить обратно совместимым способом ...

Обратите внимание, что это исправлено в Socket.IO v3, так как теперь вы можете использовать параметр auth :

// plain object
const socket = io({
  auth: {
    token: "abc"
  }
});

// or with a function
const socket = io({
  auth: (cb) => {
    cb({
      token: "abc"
    });
  }
});

Он также должен работать с функцией async :

const socket = io({
  auth: async (cb) => {
    cb({
      token: "abc"
    });
  }
});

Смотрите также:

Была ли эта страница полезной?
0 / 5 - 0 рейтинги