Node.js项目MongoDB创建管理员角色及Passport登录功能实现咨询
单管理员Node.js应用落地&Passport LocalStrategy实现方案
前置依赖安装
先安装需要的依赖包:npm install bcrypt passport passport-local express-session connect-mongo
第一步:完善Admin Mongoose模型
不要存储明文密码,模型内置哈希和密码校验逻辑,参考代码如下:
const mongoose = require('mongoose'); const bcrypt = require('bcrypt'); const adminSchema = new mongoose.Schema({ email: { type: String, required: true, unique: true }, password: { type: String, required: true } }); // 存储密码前自动哈希处理 adminSchema.pre('save', async function(next) { if (!this.isModified('password')) return next(); this.password = await bcrypt.hash(this.password, 10); next(); }); // 密码校验方法 adminSchema.methods.comparePassword = async function(inputPassword) { return await bcrypt.compare(inputPassword, this.password); }; module.exports = mongoose.model('Admin', adminSchema);
如果要通过MongoDB Compass直接创建管理员,可临时打开Node终端执行bcrypt.hash('你的管理员密码',10).then(console.log),将输出的哈希字符串直接填入Compass的password字段即可。
第二步:配置Passport LocalStrategy
在项目中新增passport配置文件,或者直接在app.js中添加如下逻辑:
const passport = require('passport'); const LocalStrategy = require('passport-local').Strategy; const Admin = require('./models/Admin'); // 适配email作为登录账号的策略配置 passport.use(new LocalStrategy({ usernameField: 'email', passwordField: 'password' }, async (email, password, done) => { try { const admin = await Admin.findOne({ email }); if (!admin) return done(null, false, { message: '账号不存在' }); const isMatch = await admin.comparePassword(password); if (!isMatch) return done(null, false, { message: '密码错误' }); return done(null, admin); } catch (err) { return done(err); } })); // 序列化用户信息到session passport.serializeUser((admin, done) => { done(null, admin.id); }); // 从session反序列化用户信息 passport.deserializeUser(async (id, done) => { try { const admin = await Admin.findById(id); done(null, admin); } catch (err) { done(err); } });
在Express入口文件中注册中间件,注意session中间件要放在passport前面:
const session = require('express-session'); const MongoStore = require('connect-mongo'); app.use(session({ secret: process.env.SESSION_SECRET || '自定义强随机密钥', resave: false, saveUninitialized: false, // 将session存储到MongoDB,重启服务不丢失登录态 store: MongoStore.create({ mongoUrl: '你的MongoDB连接字符串' }), cookie: { maxAge: 24 * 60 * 60 * 1000, // 登录态有效期1天 httpOnly: true, secure: process.env.NODE_ENV === 'production' // 生产环境HTTPS下设为true } })); app.use(passport.initialize()); app.use(passport.session());
第三步:编写登录接口与鉴权中间件
不需要开发注册相关接口,仅保留登录、鉴权、登出逻辑即可:
// 管理员登录接口 app.post('/admin/login', passport.authenticate('local', { successRedirect: '/admin/dashboard', failureRedirect: '/admin/login' })); // 管理员鉴权中间件,所有需要权限的路由都挂载该中间件 const isAdmin = (req, res, next) => { if (req.isAuthenticated()) return next(); res.redirect('/admin/login'); }; // 受保护的后台路由示例 app.get('/admin/dashboard', isAdmin, (req, res) => { res.render('dashboard', { adminInfo: req.user }); }); // 登出接口 app.post('/admin/logout', (req, res, next) => { req.logout((err) => { if (err) return next(err); res.redirect('/admin/login'); }); });
注意事项
- 生产环境必须把session密钥、数据库连接串等敏感信息放在环境变量中,禁止硬编码
- 不要自行实现密码哈希逻辑,直接使用成熟的bcrypt方案即可
- 所有和管理员操作相关的路由必须挂载
isAdmin中间件做权限校验
内容的提问来源于stack exchange,提问作者copycat
相关产品推荐
相关产品推荐

