最近学习用nodejs+express+session实现用户登录,绕不开使用passport,系统记录一下学习和实践过程
passport.js是Nodejs中的一个做登录验证的中间件,极其灵活和模块化,并且可与Express、Sails等Web框架无缝集成。passport模块本身不能做认证,所有的认证方法都以策略模式封装为插件,需要某种认证时将其添加到package.json即可。
passport功能单一,只做authenticate, 但是认证方式多种多样,具体如何认证,passport采用了策略模式把具体的实现留给了具体的strategies; 比如passport-local.
策略模式是一种设计模式,它将算法和对象分离开来,通过加载不同的算法来实现不同的行为,适用于相关类的成员相同但行为不同的场景,比如在passport中,认证所需的字段都是用户名、邮箱、密码等,但认证方法是不同的。
Passport用于用户验证,需要Nodejs+express以及相应的数据库,同时需要cookie-parse用于cookie解析,以及session和express-session用于写入和解析session。可选的,connect-flash消息提示中心件。
npm install passport --save
npm install passport-local --save
下列代码写在总配置文件app.js中
var express = require('express');
var cookieParser = require('cookie-parser');
var passport = require('passport');
var session = require('express-session');
var flash = require('connect-flash');
...
app.use(cookieParser());
app.use(session({
secret: 'assetManagement',
cookie: {maxAge: 12*60*60*1000}, //定义session失效时间
rolling: true,
resave: true,
saveUninitialized: false
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(flash());
下列代码可以单独创建一个config/passport.js文件:
var localStrategy = require('passport-local').Strategy;
var User = require('../db/user') //自己创建的数据库处理文件
module.exports = function (passport) {
//Passport将维护持久的session。
//为了实现persistent sessions,必须将经过身份验证的用户序列化到会话,并在发出后续请求时反序列化。
//标准写法
passport.serializeUser(function (user, done) {
if (!user.hasOwnProperty('username')) {
done("no user in session yet");
} else {
done(null, user);
}
});
passport.deserializeUser(function(user, done) {
if (!user.hasOwnProperty('username')) {
done('no user in seeeion yet');
} else {
done(null, user);
}
});
//=========================================================
//LOCAL LOGIN STRATEGY=====================================
//=========================================================
//自定义local login的策略
passport.use('local-login',new localStrategy({
usernameField: 'username',
passwordField: 'password',
passReqToCallback: true,
session: ture
},
function (req, username, password, done){
let userinfo = {
username: username,
password: password
};
User.UserLogin(userinfo,function (err, user) {
if (err) {
return done(err);
}
if (!user) {
return done(null, false, {message: "username or password is valid"})
}
return done(null, user);
})
}
));
}
LocalStrategy() 一个参数是 options(可选), 一个是回调函数 callback(必填)
options:
usernameField 设置 name 字段, 默认 username
passwordField 设置 password 字段, 默认 password
passReqToCallback 设置 request 是否回调函数的第一个参数, 默认 false (不是第一个参数)
session 设置 是否支持 session 会话, 保持持久化登录状态, 默认 true
callback:
done() 第一个参数返回错误信息或者null, 第二个参数返回 用户对象或者其他对象或者false
验证回调主要的作用就是去验证用户。Passport 验证一个请求,它会把请求里包含的凭证解析出来作为回调的参数。
如果验证成功就执行 done ,并且带着验证成功的用户。
如果凭证无效,比如密码不对,那么 done 应该带着 false,同时可以带着错误的message。info的格式一定是 {message: ‘ERROR MESSAGE’} 对象的属性必须是message
果验证的时候出了一些问题,应该把错误交给 done 。
下列代码写在router.js中,用于发送请求时验证登录信息
module.exports = function(app, passport) {
app.post('/signin',function(req,res,next){
passport.authenticate('local-login', function(err, user, info) {
if (err) {
return next(err);
}
if (!user) {
res.redirect('/signin');
return res.status(200).json({
message: info
});
}
return res.status(200).json({
message: "OK",
data:{
username: user.username
}
});
})(req, res, next);
})
};
app.post('/login', passport.authenticate('local', options));
passport.authenticate的第一个参数是策略的标识,第二个可选参数。
options参数解释如下:
session: 默认true,是否将用户的登录状态记录到session,一般无需修改此选项,如果设置为false,那么一旦页面跳转,浏览器无法得知你的登录状态,这个选项应该是用于RESTful API之类的程序用的,因为这类程序每次请求都会需要验证
successRedirect: 如果登录成功那么就会跳转到指定页面,如果没指定,相当于执行了next()
failureRedirect:如果登录失败,则会跳转到指定页面,如果没有指定,页面会抛出一个401 Unauthorized错误
successReturnToOrRedirect:
如果为空,此选项不生效,如果指定了url,那么当登录成功以后
https://blog.csdn.net/choelea/article/details/75033213
https://blog.csdn.net/u011468626/article/details/51010158
https://blog.csdn.net/shijue98/article/details/107389766