Возможна ли аутентификация пользовательского сокета с сеансом без паспорта? Это работает для меня, но безопасно ли? - PullRequest
0 голосов
/ 03 мая 2019

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

Из моего понимания промежуточное программное обеспечение для сеансов использует секрет, который предоставляет HMAC своего рода.Так что это не может быть подделано или изменено.Так что, если я сделаю что-то простое, как это

app.use((req, res, next) => {
    if(!req.session) return next();
    *if(req.session.userId){
        getDb().collection('users').findOne({_id: req.session.userId})
        .then(user=>{
            if(!user) return next();
            req.userId = req.session.userId;
            next();
        })
    }*else{
        next(); 
    }
});
/*
Then this 'if(!user) next()' is not required because my backend would 
always put right id of a user in session, and it can't be modified on client. 
I've put it here because it could happen that user gets deleted while session exists.
*/

Так что теперь вернемся к socket.io.Я обнаружил, что нет никакой связи между Express и сокетом, поэтому я не могу получить req.session так просто.Существует пакет под названием «express-socket.io-session», который я установил, чтобы иметь возможность доступа к сеансу на каждом сокете.Теперь мой логин / аутентификация на каждом подключенном сокете в маршруте / чате (который доступен только для аутентифицированных пользователей) выглядит аналогично на каждом экспресс-маршруте, но он находится внутри io.listener.И это так:

//Session access: socket.handshake.session
module.exports = async function(socket){ //This is mounted on io.on('connection')
    if(socket.handshake.session){
        //Login user with the session
        const user = await getDb().collection('users').findOne({_id:socket.handshake.session.userId});
        if(!user){ 
            /*If somehow there is no user found in db from session then 
             disconnect socket and send it to client*/
             return socket.disconnect();
        }
        //If user with same username is connected. Disconnect other user
        if(user.username in connectedUsers){
            const socketId = connectedUsers[user.username].socketId;
            io.sockets.connected[socketId].disconnect();
            delete connectedUsers[user.username];
        }
        connectedUsers[user.username] = {...user, socketId: socket.id}; //I DONT EXPOSE FULL USER OBJECT TO CLIENT! (only username and similar info)
        //Inform all users 
        io.sockets.emit(UPDATE_USERS, updateUsers(connectedUsers));
/*
Again updateUsers function doesn't expose full user object just count of 
users and array of usernames...
*/



//MORE CODE LIKE THIS...

Если вы не хотите читать весь код, вот что я не делаю:

  1. У моего сеанса есть секрет (не может быть подделан или изменен?) с помощью express-session.

  2. Из моих сокетов я никогда не выдаю ничего опасного, например, идентификатор пользователя или хешированный пароль, только имя пользователя, profile_pic и тому подобное.

  3. Мое приложение можно использовать, только если другой пользователь украл session.sid у другого пользователя, получив доступ к компьютеру этого пользователя.Что понятно.

Так есть ли какие-либо утечки в моем подходе?С какими проблемами я могу столкнуться?

...