Node.js express中的身份认证是Web应用开发中非常重要的一环。以下是实现身份认证的完整攻略:
Step1:安装相关模块
首先安装以下模块:
express-session
:用于维持用户的会话状态passport
:提供了运用于Node.js的身份验证中间件passport-local
:用于基于用户名和密码的身份验证策略bcryptjs
:用于加密用户密码
安装命令为:
npm install express-session passport passport-local bcryptjs
Step2:配置中间件
在创建Express应用程序的过程中,需要将以上安装的模块作为中间件使用,并指定相应的配置选项,例如:
const session = require('express-session');
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const bcrypt = require('bcryptjs');
// 配置 express 中间件
app.use(session({
secret: 'secret-key',
resave: false,
saveUninitialized: false
}));
app.use(passport.initialize());
app.use(passport.session());
// 配置本地身份验证策略
passport.use(new LocalStrategy(
function(username, password, done) {
// 在这里查询数据库,验证用户身份
User.findOne({ username: username }, function(err, user) {
if (err) { return done(err); }
if (!user) { return done(null, false, { message: 'Incorrect username.' }); }
if (!bcrypt.compareSync(password, user.password)) { return done(null, false, { message: 'Incorrect password.' }); }
return done(null, user);
});
}
));
// 用于序列化和反序列化用户对象
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
done(err, user);
});
});
在这个示例中,我们配置了一个本地身份验证策略,该策略使用了bcrypt.js密码加密算法来对用户密码进行加密,然后与数据库中的加密密码进行比较以验证用户身份。我们还实现了用户对象的序列化和反序列化,以便将用户保存在会话中。
Step3:编写登录和注册路由
在实现中间件后,需要编写登录和注册路由:
// 登录页面
app.get('/login', function(req, res) {
res.render('login');
});
app.post('/login', passport.authenticate('local', { failureRedirect: '/login' }), function(req, res) {
res.redirect('/');
});
// 注册页面
app.get('/register', function(req, res) {
res.render('register');
});
app.post('/register', function(req, res) {
const { username, password } = req.body;
const hash = bcrypt.hashSync(password, 10);
const newUser = new User({ username, password: hash });
newUser.save(function(err) {
if (err) {
console.log(err);
res.redirect('/register');
} else {
res.redirect('/login');
}
});
});
在这个示例中,我们为登录和注册分别编写了get和post路由。对于登录路由,我们使用了passport.authenticate中间件来进行身份验证,并指定了验证策略为本地验证策略。对于注册路由,我们使用bcrypt.hashSync函数对用户密码进行加密,并将加密后的密码保存到数据库中。
Step4:编写路由保护中间件
编写路由保护中间件是实现身份认证的一部分,它将确保被保护的路由只有在用户已登录的情况下才能访问。以下是一个示例:
function ensureAuthenticated(req, res, next) {
if (req.isAuthenticated()) {
return next();
} else {
res.redirect('/login');
}
}
app.get('/', ensureAuthenticated, function(req, res) {
res.render('index', { user: req.user });
});
在这个示例中,我们定义了一个中间件函数ensureAuthenticated
,该函数将检查用户是否已被验证通过(即已经登录)。如果用户已经登录,它将继续执行下一步,否则将用户重定向到登录页面。
Step5:编写用户注销路由
最后,需要实现用户注销,以便用户能够结束会话并从会话中删除存储的用户对象。以下是一个示例:
app.get('/logout', function(req, res) {
req.logout();
res.redirect('/login');
});
在这个示例中,我们使用req.logout()
函数来将用户的会话状态设置为未验证,并将用户重定向到登录页。
通过上面的步骤,我们完成了一个基础的身份认证系统。
示例说明:
下面给出两个示例,分别说明了在实现身份认证过程中使用的具体技术和方法。
示例1:使用JWT进行身份认证
在实现身份认证过程中,可以使用JSON Web Token(JWT)来生成和验证身份认证令牌。在这个示例中,我们使用jsonwebtoken模块来实现JWT身份认证。以下是示例代码:
const jwt = require('jsonwebtoken');
// 生成token
app.post('/login', function(req, res) {
const { username, password } = req.body;
if (username === 'admin' && password === 'admin') {
const token = jwt.sign({ username }, 'secret-key');
res.json({ token });
} else {
res.status(401).json({ message: 'Username or password incorrect' });
}
});
// 验证token
function verifyToken(req, res, next) {
const bearerHeader = req.headers['authorization'];
if (typeof bearerHeader !== 'undefined') {
const bearerToken = bearerHeader.split(' ')[1];
req.token = bearerToken;
jwt.verify(req.token, 'secret-key', function(err, decoded) {
if (!err) {
req.user = decoded;
next();
} else {
res.sendStatus(403);
}
});
} else {
res.sendStatus(403);
}
}
app.post('/protected', verifyToken, function(req, res) {
res.json({ message: 'Access granted', user: req.user });
});
在这个示例中,我们定义了如下路由:
/login
:用于生成JWT令牌和验证用户的登录凭证。/protected
:需要通过Token验证身份才能访问的加密路由。
在/login
路由中,我们使用jwt.sign()
来生成一个包含用户名的令牌,然后将其作为JSON响应返回给客户端。在/protected
路由中,我们使用verifyToken
中间件来验证请求中是否包含正确的Token。如果Token是有效的,我们将请求持有的用户名附加到响应中,向用户显示已通过身份验证。
示例2:使用Passport-local-mongoose进行身份认证
Passport-local-mongoose是Passport.js中间件的一个功能强大的扩展,它简化了用户身份认证的代码实现。该库提供了一种轻松的方式在Mongoose模型上构建本地Passport.js身份验证。以下是示例代码:
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const User = require('./models/user');
const mongoose = require('mongoose');
const passportLocalMongoose = require('passport-local-mongoose');
const mongoURI = 'mongodb://localhost:27017/db';
mongoose.connect(mongoURI, { useNewUrlParser: true, useUnifiedTopology: true });
// 在用户模型中使用Passport-local-mongoose插件
User.plugin(passportLocalMongoose, {
usernameField: 'email'
});
// 配置本地身份验证策略
passport.use(new LocalStrategy({ usernameField: 'email' }, User.authenticate()));
// 用于序列化和反序列化用户对象
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
在这个示例中,我们使用Mongoose来连接MongoDB数据库,并使用了passportLocalMongoose
插件。该插件为我们提供了新的模型方法User.authenticate()
,它自动在用户和密码字段上进行身份验证。我们还实现了用户对象的序列化和反序列化,类似于上一步中的做法。
通过这个示例,我们可以看出使用Passport-local-mongoose可以大大简化身份认证的代码实现,帮助减轻开发人员的工作负担。
总结:
身份认证是Web应用开发的重要组成部分,我们可以使用第三方模块和插件来实现符合标准的身份验证流程,减轻开发人员的工作量。目前,市场上有大量的身份认证解决方案以及现成的身份认证插件和模块可供选择,在实现身份认证过程中可以根据具体应用场景和需求选择合适的技术方案。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Node.js express中的身份认证的实现 - Python技术站