Определите пользователя в бэкэнде и интерфейсе, используя токены для аутентификации - PullRequest
1 голос
/ 10 марта 2019

Я бы хотел создать простой Express API с использованием Json Web Tokens.Когда пользователь пытается войти в систему, я выполняю

exports.signIn = async (req, res, next) => {
    const { username, password } = req.body;

    // get user from database
    const userQueryResult = await userQueries.getUserByName([username]);

    // return if database errors occured
    if (userQueryResult.err) {
        res.status(500).json({
            message: userQueryResult.err.message
        });
    }

    const users = userQueryResult.result;
    const user = users[0];

    // no user found
    if (!user) {
        res.status(401).json({
            message: 'Auth failed'
        });
    }

    try {
        // validate the password
        const passwordMatch = bcrypt.compareSync(password, user.passwordHash);

        // wrong credentials
        if (!passwordMatch) {
            res.status(401).json({
                message: 'Auth failed'
            });
        }

        const token = jwt.sign({
            user.id
        }, tokenSecret, {
                tokenExpiration
            });

        res.status(200).json({
            message: 'Auth succeeded',
            token
        });
    } catch (err) {
        res.status(401).json({
            message: 'Auth failed'
        });
    }
};

. Создается новый токен, который отправляется клиенту.Нужно ли отправлять объект пользователя клиенту?Потому что в настоящее время я проверяю только, аутентифицирован ли пользователь, а не какой.

Для защищенных маршрутов я проверяю, аутентифицирован ли пользователь с помощью функции промежуточного программного обеспечения

module.exports = (req, res, next) => {
    try {
        const rawToken = req.headers.authorization; // bearer <token>
        const token = rawToken.split(' ')[1]; // extract the token
        req.userData = jwt.verify(token, tokenSecret); // verify this token
        next();
    } catch (error) {
        res.status(401).json({
            message: 'Auth failed'
        });
    }
}

Так выотправить идентификатор пользователя клиенту тоже?Вы сохраняете его в локальном хранилище браузера с токеном и удаляете его при удалении токена?

Возможно, я ошибся, но в настоящее время я знаю только, как проверить, аутентифицирован ли кто-то, но не какой именно.Клиент должен знать, какой пользователь в данный момент вошел в систему.

Ответы [ 3 ]

1 голос
/ 10 марта 2019

У вас есть два варианта:

1) Вы можете сохранить пользователя в JWT.

Благодаря этому вы можете легко получить к нему доступ в бэкэнде, когда поступит другой запрос (но не во внешнем интерфейсе, поскольку JWT зашифрованы). Это может быть быстрее, чем искать пользователя каждый раз. Однако вам придется отправлять пользователя во внешний интерфейс и обратно при каждом выполнении запроса, что замедляет работу, также вы копируете данные, и если запись в базе данных изменилась, вы не заметите

2) Сохраните идентификатор пользователя или сеанса в JWT, затем найдите его в базе данных / в карте памяти, чтобы получить пользователя. Пока база данных используется mkre, вы сохраняете полосу пропускания и отслеживаете изменения.

// on login
const token = jwt.sign({ id: user.id }, tokenSecret, { tokenExpiration });
// or
const token = jwt.sign({ user }, tokenSecret, { tokenExpiration  });

Чтобы затем иметь возможность показывать данные пользователя на клиенте, вы должны отправить их в незашифрованном виде, например ::

 res.send(`Your name is ${user.name} and you got the id ${user.id}`);
1 голос
/ 10 марта 2019

Новый токен генерируется и отправляется клиенту.Нужно ли отправлять объект пользователя клиенту?Потому что в настоящее время я проверяю только, аутентифицирован ли пользователь, а не какой.

Технически вы можете отправить также объект пользователя (и любую другую информацию), но обычно вы хотите отправить толькотокен jwt, так как он содержит всю необходимую информацию (полезную нагрузку) на стороне клиента.

Так вы бы отправили идентификатор пользователя клиенту?

Так же, как и в предыдущем ответе, если вам нужен идентификатор пользователя на стороне клиента, вы включаете его в полезную нагрузку jwt.

Вы сохраняете его в локальном хранилище браузера с токеном и удаляете его при удалении токена?

Если он вам нужен как нечто постоянное (перезагрузка страницы) ихда, сохраните токен jwt или что-нибудь еще в этом отношении в локальное хранилище.

Возможно, я ошибся, но в настоящее время я знаю только, как проверить, аутентифицирован ли кто-то, но не какой именно.Клиент должен знать, какой пользователь в данный момент вошел в систему.

Что вам нужно, так это авторизация пользователя (не аутентификация), которую вы проверяете на стороне сервера.

0 голосов
/ 10 марта 2019

Я пытаюсь ответить на ваши вопросы:

Нужно ли отправлять объект пользователя и клиенту?

зависит от того, нужен ли вам пользователь, которого вы можете отправитьЭто.Я обычно храню пользовательский объект в req.user, создавая промежуточное ПО, например authMiddleware, например:

const { User } = require('../models/user');
let authenticate = function (req, res, next) {
    let token = req.cookies.access_token;
    User.findByToken(token).then((user) => {
        req.user = user;
        req.token = token;
        next();
    }).catch(e => {
        res.redirect('/');
    })
}
module.exports = {
    authenticate
}

Я предполагаю, что вы используете mongodb и mongoose.Что такое метод findByToken ()?это пользовательский метод мангуста:

// user model
const mongoose = require('mongoose');
let UserSchema = new mongoose.Schema({
   ...your model schema,
   tokens: [{  //here is tokens array
        access: {
            type: String,
            required: true
        },
        token: {
            type: String,
            required: true
        }
    }],
}
UserSchema.statics.findByToken = function (token) {
    let user = this;
    let decoded;
    try {
        decoded = jwt.verify(token, 'secret')
    } catch (e) {
        return Promise.reject();
    }
    return user.findOne({
        '_id': decoded._id,
        'tokens.access': 'auth',
        'tokens.token': token
    })
}

let User = mongoose.model('User', UserSchema);
module.exports = { User };

Так вы бы отправили идентификатор пользователя клиенту?Вы сохраняете его в локальном хранилище браузера с токеном и удаляете его при удалении токена?

после пения токена вы должны хранить токен в токенах Массив документа модели пользователя

UserSchema.methods.generateAuthToken = function () {
    let user = this;
    let access = 'auth';
    let token = jwt.sign({ '_id': user._id.toHexString(), access }, 'secret').toString();
    user.tokens = user.tokens.concat([{ access, token }]);

    return user.save().then(() => {
        return token;
    })

}

Рекомендуется хранить токен в cookie:

res.cookie('access_token', token, {
    maxAge: 3600000,
    httpOnly: true
})
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...