SocketCluster Middleware HandShake с обещанием
Я создаю приложение, которое обслуживает как http, так и ws. Пользователи сначала заходят через HTTP на сервер Laravel. Это возвращает JWT, который используется для разрешения входа через WS.
Ihv добавил MIDDLEWARE_HANDSHAKE, который получает токен и делает запрос к Laravel Server, чтобы спросить, действителен ли этот токен и есть ли у пользователя доступ к WS (не каждый зарегистрированный пользователь имеет доступ к WS);
Код клиента:
var options = {
host: '127.0.0.1:3000',
query: {
source: 'web',
token: '',
}
};
var socket;
$.post('http://127.0.0.1:8000/authenticate', {
email: 'chadd01@example.org',
password: '1234'
}, function(data, textStatus, xhr) {
options.query.token = data.token;
//ALL PERFECT UNTILL HERE
// Initiate the connection to the ws server
socket = socketCluster.connect(options)
.on('connect', function(data) {
console.log('CONNECTED', data);
})
.on('error', function(data) {
console.log('ERROR', data.message);
});
});
Код сервера SocketCluster:
scServer.addMiddleware(scServer.MIDDLEWARE_HANDSHAKE, function(request, next) {
var query = url.parse(request.url, true).query;
switch (query.source) {
case 'web':
case 'mobile-app':
validateUser(query)
.then((response) => {
next(); //Allowed
})
.catch((code) => {
next(code); //Blocked with StatusCode
});
break;
default:
next(true, 'NOT_AUTHORIZED'); // Block
break;
}
});
validateUser = (credentials = {}) => {
return new Promise((resolve, reject) => {
request({ url: API + 'webSocket/users/' + credentials.token, method: 'GET' }, (error, response, body) => {
if (response.statusCode === 200) {
resolve(body);
}
reject(response.statusCode);
});
});
};
При реализации такого промежуточного программного обеспечения, как этот, я продолжаю получать этот ответ от сервера ws, даже если проверка прошла успешно:
WebSocket connection to 'ws://127.0.0.1:3000/socketcluster/?source=web&token=<_TOKEN_>' failed: Connection closed before receiving a handshake response
(index):149 ERROR Socket hung up
Но если я реализую HANDSHAKE_MIDDLEWARE следующим образом:
scServer.addMiddleware(scServer.MIDDLEWARE_HANDSHAKE, function(request, next) {
var validUser = true;
if (validUser){
return next();
}
return next('NOT_A_VALID_USER');
});
Все идет хорошо
CONNECTED Object {id: "W067vqBc9Ii8MuIqAAAC", pingTimeout: 20000, isAuthenticated: true, authToken: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbiI6I…xOTV9.E4bLPh4Vjk9ULvfhW6prjBbVt0vOD32k63L1vlDtGrU"}
Таким образом, проблема, кажется, в обратном вызове Promise.
Любой совет, если это не правильный способ реализации?
Благодарю.
1 ответ
Основная причина, по которой JWT используется в SocketCluster, заключается в обработке входа в систему и аутентификации. Вы рассматривали только использование WS?
Посмотрите на аутентификацию SocketCluster.
Как ваш текущий HTTP-код проверяет данные для входа, вы можете сделать то же самое для WS и использовать socket.setAuthToken
установить токен (вот пример, который я использовал в своем проекте):
socket.setAuthToken({
email: credentials.email,
id: returnedData.id,
permission: returnedData.permission
});
Затем вы можете делать запросы к серверу WS, все еще использующему on / emit, и проверять, аутентифицированы ли они. Вот модифицированный фрагмент моего authCheck
функция:
const token = socket.getAuthToken();
if (token && token.email) {
console.log('Token Valid, User is: ', token.email);
// user validated - continue with your code
} else {
console.log('Token Invalid, User not authenticated.');
// respond with error message to the user
}