【问题标题】:passport deserializeUser method never called护照反序列化用户方法从未被调用
【发布时间】:2016-07-14 22:21:55
【问题描述】:

我有 200 响应登录请求,但 401 用于任何进一步的身份验证检查请求,因为 deserializeUser 从未调用过。我深入研究了护照源并注意到护照检查 req._passport.session.user 是否存在,如果不存在,它不会调用反序列化用户。

我已经搜索过有关 stackoverflow 的其他问题,看来我有具体案例。

有单一的本地策略身份验证类型,我使用 Ajax 请求进行登录请求,配置 CORS 设置,http://localhost:8080 - 前端,http://localhost:3000 后端)

我使用 bodyParse、cookieParser、快速会话、护照初始化和护照会话。 Express session secure:false 配置为我通过 http 运行身份验证请求。

你可以在这里找到我的项目(后端的package.json很好,所以你可以使用它,它没有缺少依赖项,至于前端不确定),至少你可以在那里检查代码。

后台https://github.com/rantiev/template-api 前端https://github.com/rantiev/template-angular

快速会话配置和CORS在这里https://github.com/rantiev/template-api/blob/master/modules/appConfigure.js

var path = require('path');
var bodyParser = require('body-parser');
var session = require('express-session');
var cookieParser = require('cookie-parser');
var MongoStore = require('connect-mongo')(session);

module.exports = function (app, express, config, mongoose) {

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

    app.use(function (req, res, next) {

        // Website you wish to allow to connect
        res.setHeader('Access-Control-Allow-Origin', 'http://localhost:8080');

        // Request methods you wish to allow
        res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');

        // Request headers you wish to allow
        res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With, X-AUTHENTICATION, X-IP, Content-Type, Origin, Accept, Cookie');

        // Set to true if you need the website to include cookies in the requests sent
        // to the API (e.g. in case you use sessions)
        res.setHeader('Access-Control-Allow-Credentials', true);

        // Pass to next layer of middleware
        next();
    });

    /*app.use(function (req, res, next) {
        console.log('coockie is:', req.cookies);
    });*/

    app.use(session({
        saveUninitialized: false,
        resave: false,
        secret: config.sessionsSecretToken,
        cookie: {
            secure: false
        },
        store: new MongoStore({ mongooseConnection: mongoose.connection })
    }));

    app.use(express.static(path.join(__dirname, '..' , 'public')));

};

护照配置在这里https://github.com/rantiev/template-api/blob/master/api/authentication/authenticationR.js

var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var rememberMe = require('../../modules/rememberMe');
var createAccessToken = require('../../modules/createAccessToken');

var bcrypt = require('bcrypt-nodejs');

var UserM = require('../users/userM');

module.exports = function (app, mainRouter, role) {

    passport.use(new LocalStrategy({
        usernameField: 'email',
        passwordField: 'password'
    }, function (username, password, done) {

        UserM.findOneQ({email: username})
            .then(function(user){

                if (user && bcrypt.compareSync(password, user.password)) {
                    done(null, user);
                } else {
                    done(null, false);
                }

            })
            .catch(function(err){
                done(err);
            });

    }));

    passport.serializeUser(function (user, done) {

        console.log('serialize');

        if (user) {
            createAccessToken(user, done);
        } else {
            done(null, false);
        }
    });

    passport.deserializeUser(function (token, done) {

        console.log('deserialize');

        UserM.findOneQ({accessToken: token})
            .then(function(user){

                if (user) {
                    done(null, user);
                } else {
                    done(null, false);
                }

            })
            .catch(function(err){
                done(err);
            });

    });

    app.use(passport.initialize());
    app.use(passport.session());

    mainRouter.post('/me', passport.authenticate('local'), function (req, res) {
        res.status(200).send();
    });

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

    mainRouter.get('/me', function (req, res) {

        if (!req.user) {
            res.status(401).send('Please Login!');
            return;
        }

        var currentUser = {
            id: req.user._id,
            role: req.user.role
        };

        res.status(200).json(currentUser);
    });

};

【问题讨论】:

  • 我也遇到了同样的问题,你解决了吗?
  • 不,当我有解决方案时会在这里回答。给它一个超时。到目前为止,我已尽我所能,它不起作用)
  • 我假设登录请求正在设置 cookie,然后在后续请求中传回该 cookie,并且该 cookie 具有您发出的访问令牌。
  • 没错。但是快速会话或护照会话永远不会恢复,这就是它不调用反序列化方法的原因。我不知道为什么。我看到该 cookie 设置正确,并在身份验证请求中传递给后端。
  • @Rantiev,您可能想让自己的生活更轻松,并使用cookie-session 中间件,而不是express-session 中间件,这样可以减少设置、减少时间和减少头痛。跨度>

标签: express passport.js


【解决方案1】:

如果您查看调用堆栈并发现 deserializeUser 没有被调用,因为 req._passport.session.user 未设置,那么您的问题如下。违规行在express-session 模块中:

if (!req.sessionID) {
  debug('no SID sent, generating session');
  generate();
  next();
  return;
}

如果设置了 sessionID,则永远不会调用 generate

store.generate = function(req){
 req.sessionID = generateId(req); 
 req.session = new Session(req); // THIS
 req.session.cookie = new Cookie(cookieOptions);

 if (cookieOptions.secure === 'auto') {
  req.session.cookie.secure = issecure(req, trustProxy);
 }
};

但可以设置req.sessionID,而req.session 为空,这解释了req._passport.session.user 为空—req.session 永远不会设置。

我继续追查到req.sessionID 设置的时间,对于新的 cookie,有时会设置,有时不会设置。

为什么?我不知道,希望有人能进一步调查,但基本上,教训是尝试改用 cookie-session 模块。

【讨论】:

    【解决方案2】:

    你试过maxAge吗?

    app.use(express.session({   store: sessionStore,
                                cookie: { maxAge : 3600000 } //1 Hour
                                }));
    

    【讨论】:

    • 是的,我做到了。我实际上忘记了问题的状态。无论我解决与否,似乎我已经更新了过去 1 年的所有模块并且一切正常。
    猜你喜欢
    • 2019-12-09
    • 2015-12-22
    • 2016-07-03
    • 2014-11-30
    • 2018-03-03
    • 2019-01-23
    • 1970-01-01
    • 2016-04-13
    • 2020-09-08
    相关资源
    最近更新 更多