socket.handshake.query
saat ini memungkinkan data disetel pada connect
, tetapi tidak dapat diperbarui dengan referensi sebelum reconnect
diaktifkan. Ini menyebabkan masalah saat mengotorisasi koneksi soket dengan token penyegaran.
//client
io.connect("wss://socket.server.com", {
query : {
token:"something dynamic"
}
});
Jika server dimulai ulang dan klien reconnect
, token mungkin kedaluwarsa saat mengotorisasi ulang soket.
//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
}
});
Izinkan kueri menjadi function
:
io.connect("wss://socket.server.com", {
query : function(){
return {
token:"something dynamic"
}
}
});
Dalam konstruktor Socket saat ini:
if (opts && opts.query) {
this.query = opts.query;
}
Dapat diubah menjadi ini:
if(opts && opts.query) {
this.query = typeof opts.query == 'function' && opts.query.call(this) || opts.query;
}
+1
perbaikan untuk bug #1086 juga harus menyelesaikan masalah Anda. Mengubah opsi kueri setelah koneksi berhasil berfungsi dengan versi socket.io-client yang lebih lama, tetapi dengan versi saat ini referensi ke objek kueri hilang :(
@reeltimedoktor saat ini Anda harus dapat memperbarui objek query
pada acara reconnect_attempt
:
socket.on('reconnect_attempt', function () {
socket.io.opts.query = { token: /* ... */ };
});
Solusi @darrachequesne sepertinya tidak berhasil untuk saya :(
Saya menggunakan socket.io-client
versi 2.3.0
pada klien, dengan server simpul dengan socket.io
versi 2.3.0
.
Pada klien saya melakukan ini:
socket.on('reconnect_attempt', async () => {
const newToken = await getNewToken();
socket.io.opts.query = {
token: latestToken,
};
});
Dan kemudian server mengautentikasi token menggunakan middleware yang diteruskan ke io.use()
(yang kemudian akan menyala ketika soket terhubung atau terhubung kembali, afaik?).
Saat ini autentikasi server gagal terhubung kembali, mengatakan bahwa token telah kedaluwarsa - tampaknya token baru tidak ditetapkan dengan benar ke socket.io.opts.query.token
- ada ide mengapa?
Terima kasih :)
Pembaruan: Sepertinya ada banyak tempat berbeda di objek soket tempat token auth disimpan, misalnya socket.io.engine.query.token
, socket.io.engine.transport.query.token
. Ini tidak diisi secara otomatis saat Anda menyetel socket.io.opts.query.token
. Namun, mengubah ini tetap tidak memengaruhi apa yang 'dilihat' oleh server - itu masih hanya melihat token lama.
Token juga tampaknya disertakan sebagai parameter URL di beberapa bidang url di objek soket. Mungkin ini perlu diperbarui juga?
Setelah menyelidiki lebih lanjut, tampaknya menyetel token pada socket.io.opts.query.token
sudah cukup untuk mengubah token untuk otentikasi ulang saat menghubungkan kembali - sesuatu yang lain tampaknya menjadi masalah untuk aplikasi saya, mungkin ada hubungannya dengan pembuatan token autentikasi firebase. Jadi untuk siapa pun yang menemukan ini, solusi @darrachequesne berfungsi!
Oke, anggap saya sudah memperbaikinya - Anda perlu memastikan bahwa Anda mendapatkan token baru secara sinkron dalam panggilan balik 'reconnect_attempt', yaitu jangan lakukan ini:
socket.on('reconnect_attempt', async () => {
const newToken = await getNewToken(); // won't work
socket.io.opts.query = {
token: latestToken,
};
});
Sepertinya otentikasi sisi server sedang dilakukan sebelum token baru ditetapkan. Jika Anda mendapatkan token secara sinkron (dengan mengambilnya beberapa saat sebelumnya dan menyimpannya, lalu mengambilnya kembali di callback pendengar), server mendapatkan token autentikasi baru tepat waktu untuk autentikasi koneksi ulang.
dengan "socket.io-client": "3.0.4"
saya mendapatkan kesalahan TS2341: Property 'opts' is private and only accessible within class 'Manager'.
. Saya menggunakan "typescript": "4.1.3"
Oke, anggap saya sudah memperbaikinya - Anda perlu memastikan bahwa Anda mendapatkan token baru _synchronously_ di panggilan balik 'reconnect_attempt', yaitu jangan lakukan ini:
socket.on('reconnect_attempt', async () => { const newToken = await getNewToken(); // won't work socket.io.opts.query = { token: latestToken, }; });
Sepertinya otentikasi sisi server sedang dilakukan sebelum token baru ditetapkan. Jika Anda mendapatkan token secara sinkron (dengan mengambilnya beberapa saat sebelumnya dan menyimpannya, lalu mengambilnya kembali di callback pendengar), server mendapatkan token autentikasi baru tepat waktu untuk autentikasi koneksi ulang.
Kami memiliki masalah serupa. Tetapi solusi saya saat ini adalah disconnect
dari sisi server ketika auth gagal. setelah menerima acara disconnect
pada klien, kami membuat ulang kueri/tajuk dengan panggilan janji asinkron. Pada saat mencapai reconnecting
acara, itu sudah memiliki nilai baru di query/header.
Untuk pembaca masa depan:
Perilaku opsi query
di Socket.IO v2 agak aneh, karena digunakan di keduanya:
Jadi saya tidak yakin bagaimana kita bisa memperbaikinya dengan cara yang kompatibel ke belakang...
Harap dicatat bahwa ini diperbaiki di Socket.IO v3, karena Anda sekarang dapat menggunakan opsi auth
:
// plain object
const socket = io({
auth: {
token: "abc"
}
});
// or with a function
const socket = io({
auth: (cb) => {
cb({
token: "abc"
});
}
});
Itu harus bekerja dengan fungsi async
juga:
const socket = io({
auth: async (cb) => {
cb({
token: "abc"
});
}
});
Lihat juga:
Komentar yang paling membantu
@reeltimedoktor saat ini Anda harus dapat memperbarui objek
query
pada acarareconnect_attempt
: