express+passport登陆认证
概述
passport.js是node中得一个做登录验证的中间件,极其灵活和模块化,并可与express,sails等web框架无缝集成。passport的目的只有“登录验证”,提供很多的strategies,每一个strategy是对一种验证方式的封装,比如psaaport-local,是使用本地验证,一般的用户信息存储在数据库中。
web一般有两种进行登录验证的形式:
- 用户名和密码认证登录(我们选择的)
- OAuth认证登录
策略strategy
策略是passport中最重要的概念。passport模块本身不能做认证,所有的认证方法都以策略模式封装为插件,需要某种认证时将其添加到package.json即可。
策略模式是一种设计模式,它将算法和对象分离开来,通过加载不同的算法来实现不同的行为,适用于相关类的成员相同但行为不同的场景,比如在passport中,认证所需的字段都是用户名、邮箱、密码等,但认证方法是不同的。
express结合passport实现登陆认证步骤
1. 新建项目
express -e passport
cd passport
npm install
npm install passport
npm install passport-local
2. 配置中间件:(有顺序)
- 启用connet的session中间件
- connet的session中间件,同时依赖于connect的cookieParser中间件
- 配置passport中间件
//app.js
var express = require('express');
var cookieParser = require('cookie-parser');
var session = require('express-session');
var flash = require('express-flash');
var passport = require('passport');
app.use(cookieParser());
app.use(session({...}));
app.use(passport.initialize());
app.use(passport.session());
app.use(flash())
3. 定义认证策略
下面是引用的官方示例:
var passport = require('passport')
, LocalStrategy = require('passport-local').Strategy;
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: '用户名不存在.' });
}
if (!user.validPassword(password)) {
return done(null, false, { message: '密码不匹配.' });
}
return done(null, user);
});
}
));
这里就是获取数据,然后进行比较,比较结果错误则返回错误信息,通过则返回done(null,user)
const passport = require('passport');
const bcrypt = require('bcrypt');
const LocalStrategy = require('passport-local').Strategy;
const authenticationMiddleware = require('./middleware');
// Generate Password
const saltRounds = 10;
const myPlaintextPassword = 'my-password';
const salt = bcrypt.genSaltSync(saltRounds);
const passwordHash = bcrypt.hashSync(myPlaintextPassword, salt);
const user = {
username: 'test-user',
passwordHash,
id: 1
};
function findUser (username, callback) {
if (username === user.username) {
return callback(null, user)
}
return callback(null)
}
passport.serializeUser(function (user, cb) {
cb(null, user.username)
});
passport.deserializeUser(function (username, cb) {
findUser(username, cb)
});
function initPassport () {
passport.use(new LocalStrategy(
(username, password, done) => {
findUser(username, (err, user) => {
if (err) {
return done(err)
}
// User not found
if (!user) {
console.log('User not found')
return done(null, false)
}
// Always use hashed passwords and fixed time comparison
bcrypt.compare(password, user.passwordHash, (err, isValid) => {
if (err) {
return done(err)
}
if (!isValid) {
return done(null, false)
}
return done(null, user)
})
})
}
));
passport.authenticationMiddleware = authenticationMiddleware
}
module.exports = initPassport;
这个里面的密码和用户名都是我们在前面写好的,下一步完善就需要加入数据库,然后就简单的完成了登录的本地验证策略。