password.session()中间件有什么作用?


125

我正在使用Passport.js使用“ 简易节点身份验证:设置和本地”教程构建身份验证系统

我对做什么感到困惑passport.session()

在使用了不同的中间件之后,我逐渐了解到这express.session()是通过cookie向客户端发送会话ID的原因,但是passport.session()除了之外,我对做什么以及为什么需要它感到困惑express.session()

这是我设置应用程序的方式:

// Server.js配置应用程序并设置Web服务器

//importing our modules
var express = require('express');
var app = express();
var port = process.env.PORT || 8080;
var mongoose = require('mongoose');
var passport = require('passport');
var flash = require('connect-flash');

var configDB = require('./config/database.js');

//Configuration of Databse and App

mongoose.connect(configDB.url); //connect to our database

require('./config/passport')(passport); //pass passport for configuration

app.configure(function() {

    //set up our express application

    app.use(express.logger('dev')); //log every request to the console
    app.use(express.cookieParser()); //read cookies (needed for auth)
    app.use(express.bodyParser()); //get info from html forms

    app.set('view engine', 'ejs'); //set up ejs for templating

    //configuration for passport
    app.use(express.session({ secret: 'olhosvermelhoseasenhaclassica', maxAge:null })); //session secret
    app.use(passport.initialize());
    app.use(passport.session()); //persistent login session
    app.use(flash()); //use connect-flash for flash messages stored in session

});

//Set up routes
require('./app/routes.js')(app, passport);

//launch
app.listen(port);
console.log("Server listening on port" + port);

Answers:


139

passport.session() 充当中间件来更改req对象,并将当前作为会话ID的“ user”值(来自客户端cookie)更改为真正的反序列化用户对象。

虽然其他答案也有一些好处,但我认为可以提供一些更具体的细节。

app.use(passport.session());

相当于

app.use(passport.authenticate('session'));

其中“会话”指的是与passwordJS捆绑在一起的以下策略。

https://github.com/jaredhanson/passport/blob/master/lib/strategies/session.js

特别是第59-60行:

var property = req._passport.instance._userProperty || 'user';
req[property] = user;

它实际上充当中间件,并更改req对象中“ user”属性的值以包含用户的反序列化身份。为了使其正常工作,您必须在自定义代码中包含serializeUserdeserializeUser函数。

passport.serializeUser(function (user, done) {
    done(null, user.id);
});

passport.deserializeUser(function (user, done) {
    //If using Mongoose with MongoDB; if other you will need JS specific to that schema.
    User.findById(user.id, function (err, user) {
        done(err, user);
    });
});

这将从数据库中找到正确的用户,并将其作为闭包变量传递到回调中,done(err,user);因此中的上述代码passport.session()可以替换req对象中的“ user”值,并传递到堆中的下一个中间件。


嘿,我该如何仅在会话中存储用户详细信息,我不想直接将它们存储在数据库中
Newbiee'Aug

1
“在请求标头中”?不仅在请求对象中
冒泡

我已经注意到,如果会话策略能够还原身份验证并反序列化用户。但是尽管如此,身份验证仍会转移到下一个策略,在我的场景中是facebook auth。我不知道会话策略的意义是什么,即使会话能够恢复用户,它仍然继续调用以下策略。
nishant '18年

15

文档中

在基于Connect或Express的应用程序中,需要使用password.initialize()中间件来初始化Passport。如果您的应用程序使用持久登录会话,则还必须使用passport.session()中间件。

届会

在典型的Web应用程序中,用于认证用户的凭据仅在登录请求期间传输。如果验证成功,将通过用户浏览器中设置的cookie建立并维护会话。

每个后续请求将不包含凭据,而是标识会话的唯一cookie。为了支持登录会话,Passport会将用户实例与会话进行序列化和反序列化。

请注意,启用会话支持是完全可选的,尽管建议将其用于大多数应用程序。如果启用,请确保在使用password.session()之前使用express.session(),以确保以正确的顺序还原登录会话。


1
感谢您的快速答复,但这不能回答我的问题。另外,请注意,如果您有一个Express应用程序,并且在连接到Express服务器的任何客户端上使用express.session()(无论他是否通过身份验证),都会通过Cookie为其进行会话。这取决于他是否在您应用的登录保护页面中。我仍然想知道两种中间件之间的区别。
Georges Krinker 2014年

1
@GeorgesKrinker是serializeUser()和deserializeUser方法。Express中间件将恢复会话信息,但这与护照如何管理用户信息不一定有关。会议必须通过快递补水后再进行。
Josh C.

好吧,我给人的印象是serializeUser()和deserializeUser方法在路由内的authenticate()上运行。
Georges Krinker 2014年

@GeorgesKrinker我不这么认为。使用护照时,我仅在登录时调用.authenticate。
Josh C.

app.post('/login', passport.authenticate('local'), ...
Josh C.

11

当您将使用 PassportJs用于验证用户的登录URL的一部分,但是您仍然需要某种机制来将该用户信息存储在会话中,并在以后的每个请求中进行检索(即序列化/反序列化用户)。

因此,实际上,您正在使用每个请求对用户进行身份验证,即使此身份验证不需要像登录响应中那样查找数据库或oauth。因此,护照还将会话身份验证也视为另一种身份验证策略。

要使用此策略(即命名策略)session,只需使用一个简单的快捷方式即可app.use(passport.session())。还请注意,出于明显的原因,该特定策略将希望您实现序列化和反序列化功能。


11

它只是对会话进行身份验证(由填充express.session())。它等效于:

passport.authenticate('session');

如此处的代码所示:

https://github.com/jaredhanson/passport/blob/42ff63c/lib/authenticator.js#L233


6
你什么意思?它在每个请求上运行,并且不一定具有要进行身份验证的凭据。您介意为我提供有关每个请求的工作流的更多详细信息吗?
Georges Krinker 2014年

6
是的,它可以按每个请求运行。Express生成的会话ID是唯一ID,它大致等效于浏览器随每个请求发送的身份验证令牌。此会话中存储的数据用于恢复用户的身份验证状态。
Jared Hanson

您好@JaredHanson您可以看看这个吗。我在任何地方都找不到答案?
萨拉斯·亚里亚

@JaredHanson我正在尝试使用passport.js向与OAuth2兼容的广泛使用的开源授权服务器进行身份验证。但是我遇到一个错误。您愿意帮助解决问题吗?这里是链接: stackoverflow.com/questions/38176236/...
DollarCoffee

@JaredHanson:我观察到的是,在通过google-oauth登录后,刚在护照上添加了password.user信息的req对象在站点上进行下一个新页面请求时丢失了。这是预期的行为吗?然后我不知道如何取回最近登录的用户信息?
user1102171 16-10-21
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.