Node.Js + express +护照:无法注销用户

我为Web服务器编写了一个JS脚本,其中包括使用护照和摘要策略的身份validation。 我不使用会话,但我已经尝试使用会话,它不会改变结果。 浏览器请求“/ login”路由并显示一个内置的login对话框。 validation工作正常,但我不能让用户“注销”。 问题似乎是浏览器记住login凭证并自动重新发送。 最终的结果是用户必须完全closures浏览器才能注销,但这对于此应用程序来说是一个问题。 我知道必须有办法告诉浏览器不要这样做,但我还没有弄明白。

我想出了一个破解让浏览器再次显示login对话框; 强制authentication函数返回false。 但是,我还没有想出一个方法来做到这一点每个会话。 现在,如果一个人注销,每个人都注销。 这不是一个可行的解决scheme。

有谁能告诉我我在做什么错在这里? 有一件事,我想知道的是,当我的浏览器发布到/ logout路由时,是否返回正确的响应(请参见结束)。 我返回res.json(“”),但也许有一个不同的响应,我应该发送告诉浏览器忘记会话的凭据?

我的代码如下。 任何有识之士都非常感激。 先谢谢你。

Ť

var passport = require('passport'), DigestStrategy = require('passport-http').DigestStrategy; var express = require('express'); var app = express(); app.configure(function () { app.use( "/", //the URL throught which you want to access to you static content express.static('./www') //where your static content is located in your filesystem ); app.use(express.cookieParser()); app.use(express.bodyParser()); app.use(express.session({ secret: 'keep moving forward' })); app.use(passport.initialize()); app.use(passport.session()); app.use(app.router); }); app.listen(80); //the port you want to use /** * CORS support. */ app.all('*', function(req, res, next){ if (!req.get('Origin')) return next(); // use "*" here to accept any origin // For specific domain, do similar: http://localhost' // Use an array for multiple domains, like [http://localhost', 'http://example.com' ] res.set('Access-Control-Allow-Origin', '*' ); res.set('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE'); res.set('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type, Authorization'); next(); }); // // Configure passport authentication // // Used to force the browser to display the login screen again. var forceLogin = false; passport.use(new DigestStrategy({ qop: 'auth' }, function(username, done ) { if ( !forceLogin ) { return done(null, username, "nimda"); } else { // // Forces the browser to request the user name again by returning a failure to its last request. // console.log ( "forcing user to log in" ); forceLogin = false; return done(null, false); } )); passport.serializeUser(function(user, done) { console.log( "serialize user " + user.toString() ); done(null, user.toString()); }); passport.deserializeUser(function(id, done) { console.log( "deserialize user " + id.toString() ); done(null, id); }); app.post('/login', passport.authenticate('digest', { session: true }), function(req, res) { console.log( "/login"); res.header('Cache-Control', 'no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0'); res.json({ id: req.user.id, username: req.user.username }); }); app.post('/logout', function(req, res){ req.logOut(); // NOTE: Same results as req.logout // // req.session.destroy(function (err) { // res.redirect('/'); // }); res.redirect("/"); // flag to force a login forceLogin = true; console.log( "logout"); // Is this the proper return to the browser? return res.json(""); }); 

你可以尝试以下

 req.session.destroy() req.logout() res.redirect('/') 

保存会话的新状态非常重要,如果您使用某种forms的会话存储进行持久会话(例如Redis)。 我尝试了类似的设置上面的代码,它似乎为我工作

服务器需要以某种方式通知Web浏览器,他需要刷新login信息(MD5摘要)。 为此,您可以发送401错误代码, 通常浏览器将显示loginpopup消息。

顺便说一下,所有这些会话的技巧是无用的,因为浏览器已经有了所有需要的信息自动login。

所以你可以尝试下一个代码:

 req.logout(); res.send("logged out", 401); 

晚会有点晚,但我在Google上find了这个线索,同时寻找答案,没有为我工作。 最后,我能够解决这个问题,所以我想我可以在这里发布解决scheme,供任何人在将来阅读。


所以基本上,我使用node.js,expression,护照(本地)和rethinkdb作为我的存储,我有req.logout();问题req.logout(); 没有注销我。

我的设置:

 var express = require( 'express' ); var passport = require( 'passport' ); var session = require( 'express-session' ); var RDBStore = require( 'express-session-rethinkdb' )( session ); 

我尝试了很多东西,没有任何工作,所以最后我决定手动去做,通过从数据库中删除会话logging我自己。

这里是我使用的代码:app.get('/ logout',function(req,res,next){

  if ( req.isUnauthenticated() ) { // you are not even logged in, wtf res.redirect( '/' ); return; } var sessionCookie = req.cookies['connect.sid']; if ( ! sessionCookie ) { // nothing to do here res.redirect( '/' ); return; } var sessionId = sessionCookie.split( '.' )[0].replace( 's:', '' ); thinky.r.db( 'test' ).table( 'session' ).get( sessionId ).delete().run().then( function( result ) { if ( ! result.deleted ) { // we did not manage to find session for this user res.redirect( '/' ); return; } req.logout(); res.redirect( '/' ); return; }); }); 

所以我希望这可以帮助别人:)

res.redirect('/')将结束响应,你不能再调用write(),end(),send(),json()等等

像这样:

 app.post('/logout', function(req, res){ req.logOut(); res.redirect("/"); }); 

反序列化用户应该返回一个用户而不是id:

 passport.deserializeUser(function(id, done) { findUser(id, function(err, user) { if(err) { done(err) } else { done(null, user); } } }); 

我已经做了一个简短的讨论,我意识到,摘要用户名/密码存储在浏览器(不在服务器上),所以req.logout没有帮助,没有办法从服务器清除它。 您只需closures浏览器并再次打开即可注销。

您可以在Cookie或会话中使用variables来将会话标记为注销,但是我认为我们不应该这样做,因为用户名/密码仍在浏览器中。

这是消化!