用户登录时重新连接套接字
Reconnect socket on user login
我使用由 create-react-app 创建的设置并使用 flux 进行数据管理,应用程序需要在客户端实现套接字(为此我使用 socket.io)。
目前,套接字在 Socket.js 文件中按以下方式初始化:
import io from 'socket.io-client';
import { remoteUrl } from './constants/RemoteUrl';
import SocketWorker from './utilities/SocketWorker';
let socket = io.connect(remoteUrl + '?role=user');
socket.on('statusChange', (data) => {
return SocketWorker.receiveOrderStatusChange(data);
})
export { socket };
它确实有效,但问题是它只在加载站点时尝试连接到服务器一次。当用户打开未经身份验证的站点时,它没有连接并且错过了重新连接,因此没有建立连接并且没有收到套接字事件
我尝试创建一个 class 并响应 API 以重新连接对象,例如:
import io from 'socket.io-client';
import { remoteUrl } from './constants/RemoteUrl';
import SocketWorker from './utilities/SocketWorker';
function Socket() {
this.socket = io.connect(remoteUrl + '?role=user');
this.reconnect = () => {
this.socket = io.connect(remoteUrl + '?role=user');
}
}
let socket = new Socket();
socket.socket.on('statusChange', (data) => {
return SocketWorker.receiveOrderStatusChange(data);
})
export { socket };
我尝试调用 Socket.reconnect() 方法,但它不起作用,也没有建立连接。有任何想法或替代解决方案吗?
如果有人遇到与 Socket.io 相同的问题,我设法解决这个问题的方法 API:
首先,您应该将 Socket 封装到构造函数创建的对象中,但是不需要创建重新连接方法,因为连接已经存在(并且可以通过发出的事件处理身份验证,我将在下面描述) :
import io from 'socket.io-client';
import { remoteUrl } from './constants/RemoteUrl';
import SocketWorker from './utilities/SocketWorker';
function Socket() {
this.socket = io.connect(remoteUrl + '?role=user');
this.socket.on('statusChange', (data) => {
return SocketWorker.receiveOrderStatusChange(data);
})
};
const socket = new Socket();
export { socket };
您可以在项目中的任何位置导入套接字:
import {socket} from './Socket';
您可以拨打:
socket.socket.emit('joinRoleRoom','user');
socket.socket.emit('joinIdRoom', _user._id);
在服务器端,您只需要按如下方式处理这些事件:
socket.on('joinRoleRoom', (role) => {
socket.join(role)
console.log('Client joined to: ' + role);
});
socket.on('joinIdRoom', (id) => {
console.log('Client joined to: ' + id);
socket.join(id)
});
socket会根据认证过程中获得的认证信息加入必要的房间。
sznrbrt 最初接受的答案可以工作,但要注意它有一个严重的安全漏洞。
如果您执行以下操作,攻击者只需传递所需 user_id 即可加入房间并开始接收敏感的用户信息。可能是两个人之间的私信。
socket.socket.emit('joinRoleRoom','user');
socket.socket.emit('joinIdRoom', user_id);
Socket.io 有一个选项可以通过 extraHeaders。可以使用它来传递来自客户端的令牌。服务器将使用所需的身份验证算法来解密令牌并获得 user_id
.
示例:
socket.js
import io from 'socket.io-client';
import { remoteUrl } from './constants/RemoteUrl';
import SocketWorker from './utilities/SocketWorker';
const socket = io.connect(remoteUrl + '?role=user');
const socketAuth = () => {
socket.io.opts.extraHeaders = {
'x-auth-token': 'SET_TOKEN',
};
socket.io.opts.transportOptions = {
polling: {
extraHeaders: {
'x-auth-token': 'SET_TOKEN',
},
},
};
socket.io.disconnect();
socket.io.open();
};
export { socket, socketAuth };
client.js
import { socket, socketAuth } from './socket';
//After user logs in
socketAuth();
server.js,使用包socketio-jwt-auth
io.use(jwtAuth.authenticate({
secret: 'SECRET',
succeedWithoutToken: true
}, (payload, done) => {
if (payload && payload.id) {
return done(null, payload.id);
}
return done();
}));
我使用由 create-react-app 创建的设置并使用 flux 进行数据管理,应用程序需要在客户端实现套接字(为此我使用 socket.io)。
目前,套接字在 Socket.js 文件中按以下方式初始化:
import io from 'socket.io-client';
import { remoteUrl } from './constants/RemoteUrl';
import SocketWorker from './utilities/SocketWorker';
let socket = io.connect(remoteUrl + '?role=user');
socket.on('statusChange', (data) => {
return SocketWorker.receiveOrderStatusChange(data);
})
export { socket };
它确实有效,但问题是它只在加载站点时尝试连接到服务器一次。当用户打开未经身份验证的站点时,它没有连接并且错过了重新连接,因此没有建立连接并且没有收到套接字事件
我尝试创建一个 class 并响应 API 以重新连接对象,例如:
import io from 'socket.io-client';
import { remoteUrl } from './constants/RemoteUrl';
import SocketWorker from './utilities/SocketWorker';
function Socket() {
this.socket = io.connect(remoteUrl + '?role=user');
this.reconnect = () => {
this.socket = io.connect(remoteUrl + '?role=user');
}
}
let socket = new Socket();
socket.socket.on('statusChange', (data) => {
return SocketWorker.receiveOrderStatusChange(data);
})
export { socket };
我尝试调用 Socket.reconnect() 方法,但它不起作用,也没有建立连接。有任何想法或替代解决方案吗?
如果有人遇到与 Socket.io 相同的问题,我设法解决这个问题的方法 API:
首先,您应该将 Socket 封装到构造函数创建的对象中,但是不需要创建重新连接方法,因为连接已经存在(并且可以通过发出的事件处理身份验证,我将在下面描述) :
import io from 'socket.io-client';
import { remoteUrl } from './constants/RemoteUrl';
import SocketWorker from './utilities/SocketWorker';
function Socket() {
this.socket = io.connect(remoteUrl + '?role=user');
this.socket.on('statusChange', (data) => {
return SocketWorker.receiveOrderStatusChange(data);
})
};
const socket = new Socket();
export { socket };
您可以在项目中的任何位置导入套接字:
import {socket} from './Socket';
您可以拨打:
socket.socket.emit('joinRoleRoom','user');
socket.socket.emit('joinIdRoom', _user._id);
在服务器端,您只需要按如下方式处理这些事件:
socket.on('joinRoleRoom', (role) => {
socket.join(role)
console.log('Client joined to: ' + role);
});
socket.on('joinIdRoom', (id) => {
console.log('Client joined to: ' + id);
socket.join(id)
});
socket会根据认证过程中获得的认证信息加入必要的房间。
sznrbrt 最初接受的答案可以工作,但要注意它有一个严重的安全漏洞。
如果您执行以下操作,攻击者只需传递所需 user_id 即可加入房间并开始接收敏感的用户信息。可能是两个人之间的私信。
socket.socket.emit('joinRoleRoom','user');
socket.socket.emit('joinIdRoom', user_id);
Socket.io 有一个选项可以通过 extraHeaders。可以使用它来传递来自客户端的令牌。服务器将使用所需的身份验证算法来解密令牌并获得 user_id
.
示例: socket.js
import io from 'socket.io-client';
import { remoteUrl } from './constants/RemoteUrl';
import SocketWorker from './utilities/SocketWorker';
const socket = io.connect(remoteUrl + '?role=user');
const socketAuth = () => {
socket.io.opts.extraHeaders = {
'x-auth-token': 'SET_TOKEN',
};
socket.io.opts.transportOptions = {
polling: {
extraHeaders: {
'x-auth-token': 'SET_TOKEN',
},
},
};
socket.io.disconnect();
socket.io.open();
};
export { socket, socketAuth };
client.js
import { socket, socketAuth } from './socket';
//After user logs in
socketAuth();
server.js,使用包socketio-jwt-auth
io.use(jwtAuth.authenticate({
secret: 'SECRET',
succeedWithoutToken: true
}, (payload, done) => {
if (payload && payload.id) {
return done(null, payload.id);
}
return done();
}));