首页 > 解决方案 > 如何在后端实现基于角色的访问控制

问题描述

我之前创建了一个后端,以便管理人员可以登录以访问管理页面。但是,我的问题是我想实现基于角色的访问控制,因为我希望超级管理员是唯一能够删除用户的人,而普通管理员只允许创建、阅读、更新和删除帖子。我一直无法弄清楚如何做到这一点。如果有人对实现这一点有任何建议,那将非常有帮助。以下代码是我为后端用户注册/登录/注销/令牌所拥有的一切。

用户模型.js

const mongoose = require("mongoose");
const Schema = mongoose.Schema

const UserSchema = new Schema({
    name: { type: String, required: true },
    email: { type: String, required: true },
    passwordHash: { type: String, required: true },
    role: {type: String, enum:["admin", "superadmin"]},
},
    {timestamps: true}  
);

module.exports={
    User: mongoose.model("users", UserSchema),
}

用户路由器.js

const router = require("express").Router();
const {User} = require("../models/userModel");
const bcrypt = require("bcryptjs");
const jwt = require("jsonwebtoken");

// register

router.get("/", (req, res) => {
  User.find().exec((err, users) =>{
      if(err) return res.status(400).json({ success: false, err });
      return res.status(200).json({ success: true, users: users }); 
  });
});

router.delete("/delete/:id", (req, res) => {
  User.findByIdAndRemove(req.params.id).exec((err, deleteItem) => {
      if(err){
          res.send(err);
      } 
      return res.json(deleteItem);
  })
})


router.post("/", async (req, res) => {
  try {
    const { name, email, password, passwordVerify } = req.body;

    // validation

    if (!name || !email || !password || !passwordVerify)
      return res
        .status(400)
        .json({ errorMessage: "Please enter all required fields." });

    if (password.length < 6)
      return res.status(400).json({
        errorMessage: "Please enter a password of at least 6 characters.",
      });

    if (password !== passwordVerify)
      return res.status(400).json({
        errorMessage: "Please enter the same password twice.",
      });

    const existingUser = await User.findOne({ email });
    if (existingUser)
      return res.status(400).json({
        errorMessage: "An account with this email already exists.",
      });

    // hash the password

    const salt = await bcrypt.genSalt();
    const passwordHash = await bcrypt.hash(password, salt);

    // save a new user account to the db

    const newUser = new User({
      name,
      email,
      passwordHash,
    });

    const savedUser = await newUser.save();

    // sign the token

    const token = jwt.sign(
      {
        user: savedUser._id,
      },
      process.env.JWT_SECRET
    );

    // send the token in a HTTP-only cookie

    res
      .cookie("token", token, {
        httpOnly: true,
        secure: true,
        sameSite: "none",
      })
      .send();
  } catch (err) {
    console.error(err);
    res.status(500).send();
  }
});

// log in

router.post("/login", async (req, res) => {
  try {
    const { email, password } = req.body;

    // validate

    if (!email || !password)
      return res
        .status(400)
        .json({ errorMessage: "Please enter all required fields." });

    const existingUser = await User.findOne({ email });
    if (!existingUser)
      return res.status(401).json({ errorMessage: "Wrong email or password." });

    const passwordCorrect = await bcrypt.compare(
      password,
      existingUser.passwordHash
    );
    if (!passwordCorrect)
      return res.status(401).json({ errorMessage: "Wrong email or password." });

      // const sessUser = { id: user.id, name: user.name, email: user.email };
      // req.session.user = sessUser; //Auto saves session data in mongo store
      // res.json({ msg: "Logged In Successfully", sessUser }); //sends cookie with sessionId automatically in response
    // sign the token

    const token = jwt.sign(
      {
        user: existingUser._id,
      },
      process.env.JWT_SECRET
    );

    // send the token in a HTTP-only cookie

    res
      .cookie("token", token, {
        httpOnly: true,
        secure: true,
        sameSite: "none",
      })
      .send();
  } catch (err) {
    console.error(err);
    res.status(500).send();
  }
});

router.get("/logout", (req, res) => {
  res
    .cookie("token", "", {
      httpOnly: true,
      expires: new Date(0),
      secure: true,
      sameSite: "none",
    })
    .send();
});

router.get("/loggedIn", (req, res) => {
  try {
    const token = req.cookies.token;
    if (!token) return res.json(false);

    jwt.verify(token, process.env.JWT_SECRET);

    res.send(true);
  } catch (err) {
    res.json(false);
  }
});


module.exports = router;

auth.js

const jwt = require("jsonwebtoken");

function auth(req, res, next) {
  try {
    const token = req.cookies.token;
    if (!token) return res.status(401).json({ errorMessage: "Unauthorized" });

    const verified = jwt.verify(token, process.env.JWT_SECRET, {expiresIn: "7d"});
    req.user = verified.user;

    next();
  } catch (err) {
    console.error(err);
    res.status(401).json({ errorMessage: "Unauthorized" });
  }
}

module.exports = auth;

标签: mongodbauthenticationrolesrbacuser-roles

解决方案


推荐阅读