Nodejs利用passport验证用户登录

passport验证用户登录

最近学习用nodejs+express+session实现用户登录,绕不开使用passport,系统记录一下学习和实践过程

1. Passport简介

passport.js是Nodejs中的一个做登录验证的中间件,极其灵活和模块化,并且可与Express、Sails等Web框架无缝集成。passport模块本身不能做认证,所有的认证方法都以策略模式封装为插件,需要某种认证时将其添加到package.json即可。

2. Passport策略

passport功能单一,只做authenticate, 但是认证方式多种多样,具体如何认证,passport采用了策略模式把具体的实现留给了具体的strategies; 比如passport-local.
策略模式是一种设计模式,它将算法和对象分离开来,通过加载不同的算法来实现不同的行为,适用于相关类的成员相同但行为不同的场景,比如在passport中,认证所需的字段都是用户名、邮箱、密码等,但认证方法是不同的。

3. Passport环境依赖

Passport用于用户验证,需要Nodejs+express以及相应的数据库,同时需要cookie-parse用于cookie解析,以及session和express-session用于写入和解析session。可选的,connect-flash消息提示中心件。

4. Passport安装

npm install passport --save
npm install passport-local --save

5. Passport配置和策略定义

下列代码写在总配置文件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

验证回调done()

验证回调主要的作用就是去验证用户。Passport 验证一个请求,它会把请求里包含的凭证解析出来作为回调的参数。
如果验证成功就执行 done ,并且带着验证成功的用户。
如果凭证无效,比如密码不对,那么 done 应该带着 false,同时可以带着错误的message。info的格式一定是 {message: ‘ERROR MESSAGE’} 对象的属性必须是message
果验证的时候出了一些问题,应该把错误交给 done 。

6.Passport应用

下列代码写在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);
  })
};

验证方法passport.authenticate

app.post('/login', passport.authenticate('local', options));

passport.authenticate的第一个参数是策略的标识,第二个可选参数。
options参数解释如下:
session: 默认true,是否将用户的登录状态记录到session,一般无需修改此选项,如果设置为false,那么一旦页面跳转,浏览器无法得知你的登录状态,这个选项应该是用于RESTful API之类的程序用的,因为这类程序每次请求都会需要验证
successRedirect: 如果登录成功那么就会跳转到指定页面,如果没指定,相当于执行了next()
failureRedirect:如果登录失败,则会跳转到指定页面,如果没有指定,页面会抛出一个401 Unauthorized错误
successReturnToOrRedirect:
如果为空,此选项不生效,如果指定了url,那么当登录成功以后

  1. 首先会检查req.session.returnTo是否有值,如果存在,则跳转到这里
  2. 如果req.session.returnTo为空,才跳转到指定的url
  3. 无论这个参数是什么值,只要存在,页面就一定会跳转
    注意:此方法会优先于successRedirect执行,根据第三点可知道,如果这个参数设置了值,那么再设置successRedirect就没有任何意义了。
    使用场景:比如用户访问到一个没有权限的页面,你需要将他带回登录页面,待登录成功以后,再回到此页面,就可以将returnTo设置到session里。connect-ensure-login是一个很好的模块。
    successFlash/failureFlash:
  4. 如果不设置此参数或者为false,那么在其他页面无法获取verify callback方法info参数传入的message信息
  5. 如果设置为true,那么在其他页面调用 req.flash() 就可以获取到verify callback方法info里的message信息(使用req.flash需要安装模块connect-flash)
  6. 如果设置为字符串,那么在其他页面调用 req.flash() 时,就得到这个字符串,而非info
    successMessage/failureMessage:
  7. 同上面的第一点
  8. 如果设置为true,那么verify callback方法info里的message信息会被写入到req.session.message而非通过 req.flash() 获取
  9. 如果设置为字符串,那么在其他页面,也是通过 req.session.message 获取该字符串信息
  10. 也就是说successFlash是通过 req.flash() 获取数据,而succcessMessage则是通过 req.session.messag 获取
    assignProperty: 一般无需指定此参数,但是如果你需要自己定义登录行为的话,则可以传入这个值,然后在next方法里调用 req.login 来执行登录,并且user的信息会被保存到 req[assignProperty] 里

https://blog.csdn.net/choelea/article/details/75033213
https://blog.csdn.net/u011468626/article/details/51010158
https://blog.csdn.net/shijue98/article/details/107389766

你可能感兴趣的:(nodejs,nodejs,node.js)