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:
if (opts && opts.query) {
this.query = opts.query;
}
Можно изменить на это:
if(opts && opts.query) {
this.query = typeof opts.query == 'function' && opts.query.call(this) || opts.query;
}
+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"
Хорошо, думаю, я исправил это - вам нужно убедиться, что вы получаете новый токен _синхронно_ в обратном вызове 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 немного странно, поскольку оно используется в обоих:
Так что я не уверен, как это исправить обратно совместимым способом ...
Обратите внимание, что это исправлено в 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"
});
}
});
Смотрите также:
Самый полезный комментарий
@reeltimedoktor в настоящее время вы должны быть в состоянии обновить
query
объект наreconnect_attempt
события: