如何设置PassportJS进行后端身份验证?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何设置PassportJS进行后端身份验证?相关的知识,希望对你有一定的参考价值。

因此,在连续60个小时搜索互联网之后,我决定在SO上发布一个问题。

目前我正在尝试构建一个React应用程序。它的结构是这样的,在/client下是所有反应代码(在localhost:3000)和/server处理除了认证之外的所有api请求(在localhost:5000)。 (使用MERN堆栈)

现在我真的在努力让PassportJS工作。我已经仔细阅读了这里提供的文档:http://www.passportjs.org/docs/以及使用此处提供的本地策略的示例:https://github.com/passport/express-4.x-local-example/blob/master/server.js

我现在的问题是初始身份验证(带有凭据的POST请求)很顺利。但是,我相信serializeUser并没有将user.id中的session序列化(但绝对被称为!)。当输出req.session时,我得到:

Session {
  cookie:
   { path: '/',
     _expires: null,
     originalMaxAge: null,
     httpOnly: true,
     secure: false } }

然而,似乎有些东西确实有效,因为如果我查看req.sessionStore.sessions,我会看到与user.id的饼干:

{ 'mxsYcA2DrYVz4E5q-BiBbw8_810Slj-2':
         '{"cookie":{"originalMaxAge":null,"expires":null,"httpOnly":true,"path":"/"},
           "passport":{"user":"5c93f9a655f8a740f732a9c1"}}',
        'hW_cvQeJLk7JpLxK7TZVzIMuOEMi6-6w':
         '{"cookie":{"originalMaxAge":null,"expires":null,"httpOnly":true,"path":"/"},
           "passport":{"user":"5c93f9a655f8a740f732a9c1"}}',
        '7_2AWWdijpVVl6OFrmauorBt1Q4crBGa':
         '{"cookie":{"originalMaxAge":null,"expires":null,"httpOnly":true,"path":"/"},
           "passport":{"user":"5c93f9a655f8a740f732a9c1"}}'
}

除非服务器重新启动,否则这些cookie似乎会在页面刷新期间保留。


我不确定要提供什么代码,但我可以在必要时添加其他代码段。

passport.js

var mongoose = require('mongoose');
var User = mongoose.model('User');
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;

function verifyPassword(user, password) {
  return (user.password == password);
}

passport.use(new LocalStrategy(
  function(username, password, done) {
    User.findOne({ username: username }, function (err, user) {
      if (err) {
        return done(err);
      } else if (!user) {
        return done(null, false);
      } else if (!verifyPassword(user, password)) {
        return done(null, false);
      } else {
        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);
  });
});

AuthRoutes.js

var passport = require('passport');

module.exports = function(app) {
  app.post('/auth', passport.authenticate('local', {
    successRedirect: '/success',
    failureRedirect: '/invalid'
  }));

  app.get('/auth', passport.authenticate('local', {
    successRedirect: '/success',
    failureRedirect: '/invalid'
  }));

  app.get('/success', function(req, res) {
    console.log('success');
    console.log(req.session);
    res.sendStatus(200);
  });

  app.get('/invalid', function(req, res) {
    console.log('invalid');
    console.log(req.session);
    res.sendStatus(403);
  });

  app.get('/logout', function(req, res) {
    req.logout();
  });
};

server.js

const express = require('express');
const process = require('process');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const session = require('express-session');
const passport = require('passport');
const cors = require('cors');

const app = express();

// Prevents CORS issues
app.use(cors());

// Decides Port
const port = process.env.PORT || 5000;

// MongoDB
const User = require('./api/models/UserModel');
const db_name = "testdb";
mongoose.Promise = global.Promise;
mongoose.connect(process.env.MONGODB_URI+"/"+db_name);

app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

app.use(session({
  secret: 'this_is_my_secret_salt',
  resave: false,
  saveUninitialized: true,
  cookie: {secure: true}
}));
require("./config/passport");
app.use(passport.initialize());
app.use(passport.session());

// Add Auth Routes
var authRoutes = require('./api/routes/AuthRoutes');
authRoutes(app);

// console.log that your server is up and running
app.listen(port, () => console.log(`Listening on port ${port}`));

我知道这不是最可重复的代码,但任何帮助或建议都将非常感激。我可以编辑问题,使其更容易访问!


编辑1

所以我现在能够在会话中获得user.id。我这样做是通过将我的cors声明更改为app.use(cors({credentials: true, origin: 'http://localhost:3000'}));然后提供POSTGET请求的凭据。不幸的是,即使存在user,我仍然没有获得认证。


编辑2

我已在上面的代码中更正了deserializeUser函数

答案

我不知道你错过了什么但是这个护照配置代码在最近的项目中对我有用:

app.js中的Passport配置:

const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const User = require('./models/User');

// Passport configuration
app.use(
  require('express-session')({
    cookie: { maxAge: 43200000 },
    secret: 'secret',
    resave: false,
    saveUninitialized: true
  })
);
app.use(passport.initialize());
app.use(passport.session());
passport.use(new LocalStrategy(User.authenticate()));
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());

User.js中的用户模型:

const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const passportLocalMongoose = require('passport-local-mongoose');

const User = new Schema({
  username: {
    type: String,
    required: true
  },
  password: {
    type: String,
    required: true
  },
  isAdmin: {
    type: Boolean,
    default: false
  }
});

User.plugin(passportLocalMongoose);

module.exports = mongoose.model('User', User);

认证路线:

// @route   POST /register
// @desc    Register new user
// @access  Public
router.post('/register', (req, res) => {
  const newUser = new User({
    username: req.body.username
  });
  User.register(newUser, req.body.password, (err, user) => {
    if (err) {
      res.redirect('/register'); //failure redirect
    }
    passport.authenticate('local')(req, res, () => {
      res.redirect('/programs'); //success redirect
    });
  });
});

// @route   POST /login
// @desc    
// @access  Public
router.post(
  '/login',
  passport.authenticate('local', {
    successRedirect: '/programs',
    failureRedirect: '/login'
  })
);

希望这会有所帮助,问候。

以上是关于如何设置PassportJS进行后端身份验证?的主要内容,如果未能解决你的问题,请参考以下文章

javascript PassportJS身份验证设置#passportjs #cookiesession #nodejs

如果用户通过一次身份验证,防止用户再次登录passportjs?

Express Passportjs在路由器回调中未进行身份验证

Express + PassportJS 无法读取 flash 消息

PassportJs 身份验证无限循环和执行(默认)查询

没有会话的 Passport js 身份验证