Рубрики
Без рубрики

Аутентификация и авторизация в узле JS

Очень простая статья для понимания аутентификации и авторизации с использованием NODEJS & MYSQL.

Автор оригинала: Manash Kumar Chakrobortty.

Аутентификация и авторизация пользователя является одной из важных элементов любого веб-приложения. Есть несколько видов способа обработки аутентификации, мы можем полагаться на стороннюю службу, такую как паспорт. Но в этой статье мы будем использовать очень простой и самостоятельный подход, который поможет нам понять основную часть аутентификации.

Технология используется

  • База данных: MySQL
  • Пароль хэш: bcryptjs
  • Токен: jwt.

Базовая структура

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

В папке маршрутов мы создадим файл auth.js для маршрутов, связанных с аутентификацией. Маршруты/auth.js.

const router = require('express').Router();
const userController = require('../controllers/user.controller');

// Register a new User
router.post('/register', userController.register);

// Login
router.post('/login', userController.login);

module.exports = router;

index.js.

const express = require('express');
const app = express();

// Import Routes
const authRoute = require('./routes/auth');

// Route Middlewares
app.use('/api/users', authRoute);

app.listen(3005, () => console.log('Server is running'));

Регистрация/регистрация

Мы уже определили маршрут для регистрации. Теперь мы создадим папку контроллеров для папки контроллеров и моделей для моделей. Эта структура не требуется, у вас может быть разная структура или вы можете сделать все в одном файле JS.

Так что в контроллере регистрация должна быть выглядеть так Контроллеры/user.controller.js.

// Register a new User
exports.register = async (req, res) => {
    
    //Hash password
    const salt = await bcrypt.genSalt(10);
    const hasPassword = await bcrypt.hash(req.body.password, salt);

    // Create an user object
    const user = new User({
        mobile: req.body.mobile,
        email: req.body.email,
        name: req.body.name,
        password: hasPassword,
        status: req.body.status || 1
    });
    // Save User in the database
    try {
        const id = await User.create(user);
        user.id = id;
        delete user.password;
        res.send(user);
    }
    catch (err){
        res.status(500).send(err);
    }    
};

Здесь мы использовали пакет Bcryptjs для хеш-пароля. И использовал MySQL в качестве базы данных.

Модели/user.model.js.

User.create = async (newUser) => {
    let insert = await sql.query("INSERT INTO user SET ?", newUser);
    if( insert.insertId ) {
        return insert.insertId;
    }
    else {
        return;
    }
};

Авторизоваться

Здесь мы должны проверить адрес электронной почты или мобильный телефон против предоставленного пароля. Если предоставлена информация правильная, то мы должны генерировать токен и вернуться к клиенту. Поэтому изначально мы проверим на наличие электронной почты или мобильного телефона в нашей базе данных, если пользователь существует, то позвонит bcrypt.compare () Функция BCRYPTJS. Тогда мы позвоним jsonwybtokok за токен и отправьте обратно к клиенту.

Теперь мы увидим реализацию.

Контроллеры/user.controller.js.

// Login
exports.login = async (req, res) => {
    try {
        // Check user exist
        const user = await User.login(req.body.mobile_or_email);
        if (user) {
            const validPass = await bcrypt.compare(req.body.password, user.password);
            if (!validPass) return res.status(400).send("Mobile/Email or Password is wrong");

            // Create and assign token
            const token = jwt.sign({id: user.id, user_type_id: user.user_type_id}, config.TOKEN_SECRET);
            res.header("auth-token", token).send({"token": token});
            // res.send("Logged IN");
        }
    }
    catch (err) {
        if( err instanceof NotFoundError ) {
            res.status(401).send(`Mobile/Email or Password is wrong`);
        }
        else {
            let error_data = {
                entity: 'User',
                model_obj: {param: req.params, body: req.body},
                error_obj: err,
                error_msg: err.message
            };
            res.status(500).send("Error retrieving User");
        }
    }   
    
};

Модели/user.model.js.

User.login = async (value) => {
    let row = await sql.query(`SELECT * FROM user WHERE mobile = ? OR email = ?`, [value, value]);
    if( row.length ) {
        return row[0];
    }
    else {
        throw new NotFoundError("User does not exist");
    }
};

Аутентификация и авторизация

Мы часто используем взаимозаменяемо, аутентификацию и авторизацию, но эти слова представляют принципиально разные функции.

Проще говоря, аутентификация – это процесс проверки того, кто является пользователем, в то время как разрешение – это процесс проверки того, к чему у них есть доступ.

Первоначально мы просто проверим токен в заголовке запроса на ограничениями маршрутов, а затем разрешите или запретить запрос. Тогда мы проверим зарегистрированные разрешенные маршруты пользователя для доступа.

Чтобы удержать это просто, мы сохраняем поле user_type_id и с учетом значения /Нормальный пользователь. Теперь создавая среднюю посуду, чтобы сделать эту работу. помощники/auth.middleware.js.

const config = require("../config/config");
const jwt = require("jsonwebtoken");

exports.loggedIn = function (req, res, next) {
    let token = req.header('Authorization');
    if (!token) return res.status(401).send("Access Denied");

    try {
        if (token.startsWith('Bearer ')) {
            // Remove Bearer from string
            token = token.slice(7, token.length).trimLeft();
        }
        const verified = jwt.verify(token, config.TOKEN_SECRET); 
        if( verified.user_type_id === 2 ){ // Check authorization, 2 = Customer, 1 = Admin
            let req_url = req.baseUrl+req.route.path;
            if(req_url.includes("users/:id") && parseInt(req.params.id) !== verified.id){
                return res.status(401).send("Unauthorized!");
            }
        }
        req.user = verified;
        next();
    }
    catch (err) {
        res.status(400).send("Invalid Token");
    }
}

exports.adminOnly = async function (req, res, next) {
    if( req.user.user_type_id === 2 ){
        return res.status(401).send("Access Denied");
    }  
    next();
}

Полный исходный код

https://github.com/manashcse11/express/tree/master/auth