/ / Cách triển khai Kiểm soát truy cập dựa trên vai trò trong Express.js REST API bằng Passport.js và JWT

Cách triển khai Kiểm soát truy cập dựa trên vai trò trong Express.js REST API bằng Passport.js và JWT

Kiểm soát truy cập dựa trên vai trò là một cơ chế xác thực an toàn. Bạn có thể sử dụng nó để hạn chế quyền truy cập vào các tài nguyên cụ thể đối với những người dùng có vai trò nhất định.


Loại xác thực này giúp quản trị viên hệ thống kiểm soát quyền theo vai trò được chỉ định của người dùng. Mức độ kiểm soát chi tiết này thêm một lớp bảo mật, cho phép các ứng dụng ngăn chặn truy cập trái phép.


Triển khai cơ chế kiểm soát truy cập dựa trên vai trò bằng Passport.js và JWT

Kiểm soát truy cập dựa trên vai trò (RBAC) là một cơ chế phổ biến được sử dụng để thực thi các hạn chế truy cập trong ứng dụng dựa trên vai trò và quyền của người dùng. Có nhiều phương pháp khác nhau để thực hiện cơ chế RBAC.

Hai cách tiếp cận phổ biến bao gồm sử dụng các thư viện RBAC chuyên dụng như kiểm soát truy cập hoặc tận dụng các thư viện xác thực hiện có để triển khai cơ chế.

Một máy tính xách tay đang mở với trình chỉnh sửa mã hiển thị trên màn hình

Trong trường hợp này, Mã thông báo web JSON (JWT) cung cấp một cách an toàn để truyền thông tin xác thực, trong khi Passport.js đơn giản hóa quy trình xác thực bằng cách cung cấp phần mềm trung gian xác thực linh hoạt.

Sử dụng phương pháp này, bạn có thể gán vai trò cho người dùng và mã hóa chúng trong JWT khi họ xác thực. Sau đó, bạn có thể sử dụng JWT để xác minh danh tính và vai trò của người dùng trong các yêu cầu tiếp theo, cho phép kiểm soát truy cập và ủy quyền dựa trên vai trò.

Cả hai cách tiếp cận đều có ưu điểm và có thể hiệu quả trong việc triển khai RBAC. Việc lựa chọn phương pháp nào để thực hiện sẽ phụ thuộc vào các yêu cầu cụ thể của dự án của bạn.

Thiết lập dự án Express.js

Để bắt đầu, hãy thiết lập một dự án Express.js cục bộ. Sau khi bạn thiết lập dự án, hãy tiếp tục và cài đặt các gói sau:

 npm install cors dotenv mongoose cookie-parser jsonwebtoken mongodb 
  passport passport-local

Tiếp theo, tạo cơ sở dữ liệu MongoDB hoặc thiết lập một cụm trên MongoDB Atlas. Sao chép URI kết nối cơ sở dữ liệu và thêm nó vào một .env tệp trong thư mục gốc của dự án của dự án của bạn:

 CONNECTION_URI="connection URI" 

Định cấu hình kết nối cơ sở dữ liệu

Trong thư mục gốc, tạo mới tiện ích/db.js tệp và thêm mã bên dưới để thiết lập kết nối với cụm MongoDB chạy trên Atlas bằng Mongoose.

 const mongoose = require('mongoose');

const connectDB = async () => {
  try {
    await mongoose.connect(process.env.CONNECTION_URI);
    console.log("Connected to MongoDB!");
  } catch (error) {
    console.error("Error connecting to MongoDB:", error);
  }
};

module.exports = connectDB;

Xác định mô hình dữ liệu

Trong thư mục gốc, tạo mới mô hình/user.model.js tệp và thêm mã sau để xác định mô hình dữ liệu cho dữ liệu của người dùng bằng Mongoose.

 const mongoose = require('mongoose');

const userSchema = new mongoose.Schema({
  username: String,
  password: String,
  role: String
});

module.exports = mongoose.model('User', userSchema);

Tạo Trình điều khiển cho Điểm cuối API

Tạo một cái mới bộ điều khiển/user.controller.js tập tin trong thư mục gốc và thêm mã dưới đây.

Đầu tiên, thực hiện các nhập khẩu này:

 const User = require('../models/user.model');
const passport = require('passport');
const { generateToken } = require('../middleware/auth');
require('../middleware/passport')(passport);

Tiếp theo, xác định logic để quản lý chức năng đăng ký và đăng nhập của người dùng:

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

  try {
    await User.create({ username, password, role });
    res.status(201).json({ message: 'User registered successfully' });
  } catch (error) {
    console.log(error);
    res.status(500).json({ message: 'An error occurred!' });
  }
};

exports.loginUser = (req, res, next) => {
  passport.authenticate('local', { session: false }, (err, user, info) => {
    if (err) {
      console.log(err);

      return res.status(500).json({
        message: 'An error occurred while logging in'
      });
    }

    if (!user) {
      return res.status(401).json({
        message: 'Invalid login credentials'
      });
    }

    req.login(user, { session: false }, (err) => {
      if (err) {
        console.log(err);

        return res.status(500).json({
          message: 'An error occurred while logging in'
        });
      }

      const { _id, username, role } = user;
      const payload = { userId: _id, username, role };
      const token = generateToken(payload);
      res.cookie('token', token, { httpOnly: true });
      return res.status(200).json({ message: 'Login successful' });
    });
  })(req, res, next);
};

Các người dùng đăng ký chức năng xử lý việc đăng ký người dùng mới bằng cách trích xuất tên người dùng, mật khẩu và vai trò từ phần thân yêu cầu. Sau đó, nó tạo một mục nhập người dùng mới trong cơ sở dữ liệu và phản hồi bằng thông báo thành công hoặc lỗi nếu có xảy ra trong quá trình.

Mặt khác, các người dùng đăng nhập chức năng tạo điều kiện cho người dùng đăng nhập bằng cách sử dụng chiến lược xác thực cục bộ do Passport.js cung cấp. Nó xác thực thông tin đăng nhập của người dùng và trả lại mã thông báo khi đăng nhập thành công, mã này sau đó được lưu trữ trong cookie cho các yêu cầu xác thực tiếp theo. Nếu có bất kỳ lỗi nào xảy ra trong quá trình đăng nhập, nó sẽ trả về một thông báo thích hợp.

Cuối cùng, thêm mã triển khai logic tìm nạp tất cả dữ liệu của người dùng từ cơ sở dữ liệu. Chúng tôi sẽ sử dụng điểm cuối này làm tuyến đường hạn chế để đảm bảo rằng chỉ những người dùng được ủy quyền có vai trò quản trị viên có thể truy cập điểm cuối này.

 exports.getUsers = async (req, res) => {
  try {
    const users = await User.find({});
    res.json(users);
  } catch (error) {
    console.log(error);
    res.status(500).json({ message: 'An error occurred!' });
  }
};

Thiết lập chiến lược xác thực cục bộ Passport.js

Để xác thực người dùng sau khi họ cung cấp thông tin đăng nhập, bạn cần thiết lập chiến lược xác thực cục bộ.

Tạo một cái mới phần mềm trung gian/hộ chiếu.js tập tin trong thư mục gốc và thêm mã sau đây.

 const LocalStrategy = require('passport-local').Strategy;
const User = require('../models/user.model');

module.exports = (passport) => {
  passport.use(
    new LocalStrategy(async (username, password, done) => {
      try {
        const user = await User.findOne({ username });

        if (!user) {
          return done(null, false);
        }

        if (user.password !== password) {
          return done(null, false);
        }

        return done(null, user);
      } catch (error) {
        return done(error);
      }
    })
  );
};

Mã này xác định chiến lược passport.js cục bộ để xác thực người dùng dựa trên tên người dùng và mật khẩu được cung cấp của họ.

Lúc đầu, nó truy vấn cơ sở dữ liệu để tìm người dùng có tên người dùng phù hợp và sau đó tiến hành xác thực mật khẩu của họ. Do đó, nó trả về đối tượng người dùng đã được xác thực nếu quá trình đăng nhập thành công.

Tạo phần mềm trung gian xác minh JWT

Bên trong phần mềm trung gian thư mục, tạo tệp auth.js mới và thêm đoạn mã sau để xác định phần mềm trung gian tạo và xác minh JWT.

 const jwt = require('jsonwebtoken');
const secretKey = process.env.SECRET_KEY;

const generateToken = (payload) => {
  const token = jwt.sign(payload, secretKey, { expiresIn: '1h' });
  return token;
};

const verifyToken = (requiredRole) => (req, res, next) => {
  const token = req.cookies.token;

  if (!token) {
    return res.status(401).json({ message: 'No token provided' });
  }

  jwt.verify(token, secretKey, (err, decoded) => {
    if (err) {
      return res.status(401).json({ message: 'Invalid token' });
    }

    req.userId = decoded.userId;

    if (decoded.role !== requiredRole) {
      return res.status(403).json({
        message: 'You do not have the authorization and permissions to access this resource.'
      });
    }

    next();
  });
};

module.exports = { generateToken, verifyToken };

Các tạoToken chức năng tạo JWT với thời gian hết hạn được chỉ định, trong khi xác minhToken chức năng kiểm tra xem mã thông báo có tồn tại và hợp lệ hay không. Ngoài ra, nó cũng xác minh rằng mã thông báo đã giải mã có chứa vai trò bắt buộc, về cơ bản, đảm bảo rằng chỉ những người dùng có vai trò và quyền được ủy quyền mới có quyền truy cập.

Để ký JWT một cách duy nhất, bạn cần tạo một khóa bí mật duy nhất và thêm nó vào .env tập tin như hình dưới đây.

 SECRET_KEY="This is a sample secret key." 

Xác định các tuyến API

Trong thư mục gốc, tạo một thư mục mới và đặt tên là routes. Trong thư mục này, tạo một thư mục mới userRoutes.jsvà thêm mã sau đây.

 const express = require('express');
const router = express.Router();
const userControllers = require('../controllers/userController');
const { verifyToken } = require('../middleware/auth');

router.post('/api/register', userControllers.registerUser);
router.post('/api/login', userControllers.loginUser);

router.get('/api/users', verifyToken('admin'), userControllers.getUsers);

module.exports = router;

Mã này xác định các tuyến HTTP cho API REST. Các người dùng định tuyến cụ thể, các máy chủ là tuyến được bảo vệ. Bằng cách giới hạn quyền truy cập cho người dùng với quản trị viên vai trò, bạn thực thi hiệu quả kiểm soát truy cập dựa trên vai trò.

Cập nhật tệp máy chủ chính

mở của bạn máy chủ.js tập tin và cập nhật nó như sau:

 const express = require('express');
const cors = require('cors');
const cookieParser = require('cookie-parser');
const app = express();
const port = 5000;
require('dotenv').config();
const connectDB = require('./utils/db');
const passport = require('passport');
require('./middleware/passport')(passport);

connectDB();

app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(cors());
app.use(cookieParser());
app.use(passport.initialize());

const userRoutes = require('./routes/userRoutes');
app.use("https://www.smartreviewaz.com/", userRoutes);

app.listen(port, () => {
  console.log(`Server is running on port ${port}`);
});

Cuối cùng, khởi động máy chủ phát triển để chạy ứng dụng.

 node server.js 

Tận dụng cơ chế RBAC để nâng cao hệ thống xác thực của bạn

Triển khai kiểm soát truy cập dựa trên vai trò là một cách hiệu quả để tăng cường bảo mật cho các ứng dụng của bạn.

Mặc dù việc kết hợp các thư viện xác thực hiện có để thiết lập một hệ thống RBAC hiệu quả là một cách tiếp cận tuyệt vời, nhưng việc tận dụng các thư viện RBAC để xác định rõ ràng vai trò của người dùng và gán quyền cung cấp một giải pháp thậm chí còn mạnh mẽ hơn, cuối cùng là tăng cường bảo mật tổng thể cho ứng dụng của bạn.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *