会话不能正确地从存储中获得,使用express-session和passportjs

我正在使用passportexpress-sessionconnect-pg-simple

问题是会话不能正确地从存储中获得 ,在哪里得到正确的(我希望,但怀疑)保存。

我的设置是一样的,就像我在许多教程中find的一样。

server.js:

 import express from 'express'; import next from 'next'; import bodyParser from 'body-parser'; import session from 'express-session'; import connectPgSimple from 'connect-pg-simple'; const sessionStorage = connectPgSimple(session); import initAuthentication from '!/server/authentication'; const dev = process.env.NODE_ENV !== 'production'; // eslint-disable-line const port = process.env.PORT || 3000; // eslint-disable-line const app = next({ dev }); app.prepare() .then(() => { const server = express(); server.use(express.static('public')); /* Note Since version 1.5.0, the cookie-parser middleware no longer needs to be used for this module to work. This module now directly reads and writes cookies on req/res. Using cookie-parser may result in issues if the secret is not the same between this module and cookie-parser. https://www.npmjs.com/package/express-session */ // server.use(cookieParser()); server.use(bodyParser.json()); // for parsing application/json server.use(bodyParser.urlencoded({ extended: true })); // for parsing application/x-www-form-urlencoded server.use(session({ secret: 'keyboard cat', store: new sessionStorage(), resave: false, saveUninitialized: false, cookie: { secure: false, maxAge: 30 * 24 * 60 * 60 * 1000 }}) ); initAuthentication(server); }); 

authentication.js:

 import passport from 'passport'; import LocalStrategy from 'passport-local'; import bcrypt from 'bcrypt'; import {User} from '!/server/db'; import util from 'util'; User.prototype.validPassword = function(password) { return bcrypt.compareSync(password, this.passwordHash); }; User.authenticate = (username, password, done) => { User.findOne({where: {nickname: username}}).then(user => { if (!user) { return done(null, false, { message: 'Неверное имя пользователя.' }); } if (!user.validPassword(password)) { return done(null, false, { message: 'Неверный пароль.' }); } return done(null, user); }).catch(err => { return done(err); }); }; export default function initAuthentication(server) { server.use(passport.initialize()); server.use(passport.session()); passport.use('local-signIn', new LocalStrategy(User.authenticate)); passport.serializeUser((user, done) => { console.log('> serializeUser "'+user.nickname+'" ('+user.id+')'); done(null, user.id); }); passport.deserializeUser((id, done) => { console.log('> deserializeUser with id: ' + id) User.findById(id).then(user => { done(null, user); }).catch(error => { console.log('Error in passport.deserializeUser: ' + error); done(error, null); }); }); server.post('/user/login', passport.authenticate('local-signIn'), (req, res) => { // If this function gets called, authentication was successful. // `req.user` contains the authenticated user. console.log('Authenticated user "'+req.user.nickname+'"'); req.login(req.user, (err)=> { if (err) console.log(err); console.log('\t Session established for user "'+req.user.nickname+'"'); res.json(req.user); }); } ); function logAuthenticationStatus(req, res, next) { console.log('Authentication status:') console.log('\treq.cookies: ' + util.inspect(req.cookies)); console.log('\treq.isAuthenticated: ', req.isAuthenticated()); console.log('\treq.session: ', req.session); if (req.user) { console.log('\tLogged in as "'+req.user.nickname+'"'); } else { console.log('\tNot logged in'); } next(); } server.use(logAuthenticationStatus); server.get('/logout', function(req, res){ req.logout(); res.redirect('/'); }); } 

有趣的部分是“express-session”的debugging输出,这要归功于令人惊叹的npm-package debugging 。

所以,当/user/login的请求到来时,用username = AntonAL,会发生以下情况:

 Executing (default): SELECT "id", "nickname", "email", "password", "passwordHash", "lastLoggedIn", "createdAt", "updatedAt" FROM "users" AS "user" WHERE "user"."nickname" = 'AntonAL' LIMIT 1; > serializeUser "AntonAL" (1) Authenticated user "AntonAL" > serializeUser "AntonAL" (1) Session established for user "AntonAL" express-session saving qiQfhyAvDDPD7muJLtGdZudKqMug0aAC +23ms express-session split response +0ms express-session set-cookie connect.sid=s%3AqiQfhyAvDDPD7muJLtGdZudKqMug0aAC.0wIcunkcEjhaUzs4H7w4uuv6u%2FBKXMROuAm6%2FG0vVQw; Path=/; Expires=Sat, 30 Sep 2017 10:55:31 GMT; HttpOnly +1ms info: POST /user/login 200 50ms statusCode=200, url=/user/login, host=localhost:3000, content-type=application/json, origin=http://localhost:3000, accept-encoding=gzip, deflate, connection=keep-alive, accept=application/json, user-agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/603.3.8 (KHTML, like Gecko) Version/10.1.2 Safari/603.3.8, referer=http://localhost:3000/user/login, content-length=44, accept-language=ru, method=POST, httpVersion=1.1, originalUrl=/user/login, , responseTime=50, user=AntonAL 

所以,会话保存在分贝,让我们来看看:

 SELECT * FROM session WHERE sid='qiQfhyAvDDPD7muJLtGdZudKqMug0aAC';` sid | sess | expire ----------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+--------------------- qiQfhyAvDDPD7muJLtGdZudKqMug0aAC | {"cookie":{"originalMaxAge":2592000000,"expires":"2017-09-30T10:55:31.514Z","secure":false,"httpOnly":true,"path":"/"},"passport":{"user":1}} | 2017-09-30 13:55:32 (1 row) 

到现在为止还挺好。

现在,我要求一个网站的主页,并得到如下:

 info: GET / 200 486ms statusCode=200, url=/, host=localhost:3000, accept-encoding=gzip, deflate, cookie=connect.sid=s%3AO6rS2cPlQ6JDaUUxxYRAg-VI5MmldaRE.M4iFzpVZP9fNa%2FLEomsMD8D9LjA1uFnDMnXT%2FHR3wyk; meteor_login_token=4YvVuK0V4adQJaMM2setEAx9_Ki7q6At19YfAvwyOJ8; _ga=GA1.1.1413606909.1501852025, connection=keep-alive, upgrade-insecure-requests=1, accept=text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8, user-agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/603.3.8 (KHTML, like Gecko) Version/10.1.2 Safari/603.3.8, referer=http://localhost:3000/user/login, cache-control=max-age=0, accept-language=ru, method=GET, httpVersion=1.1, originalUrl=/, , responseTime=486, user=null express-session fetching O6rS2cPlQ6JDaUUxxYRAg-VI5MmldaRE +516ms express-session fetching O6rS2cPlQ6JDaUUxxYRAg-VI5MmldaRE +1ms express-session fetching O6rS2cPlQ6JDaUUxxYRAg-VI5MmldaRE +4ms express-session fetching O6rS2cPlQ6JDaUUxxYRAg-VI5MmldaRE +1ms express-session fetching O6rS2cPlQ6JDaUUxxYRAg-VI5MmldaRE +1ms express-session fetching O6rS2cPlQ6JDaUUxxYRAg-VI5MmldaRE +0ms express-session no session found +1ms Authentication status: req.cookies: undefined req.isAuthenticated: false req.session: Session { cookie: { path: '/', _expires: 2017-09-30T11:15:52.123Z, originalMaxAge: 2592000000, httpOnly: true, secure: false } } Not logged in express-session no session found +7ms 

我看到,“快速会话”试图使用数据库中不存在的另一个SID O6rS2cPlQ6JDaUUxxYRAg-VI5MmldaRE获取会话。

为什么会发生?

AFAIK,它应该取SID = qiQfhyAvDDPD7muJLtGdZudKqMug0aAC

我的设置有哪些问题?

一个秘密的密钥,'cookies分析器'不使用,根据重新考虑'注意从版本1.5.0,cookie分析器中间件不再需要'…

我完全坚持这一点。

请帮忙。


sid一代有些不妥

当我手动更改存储会话的sid以使其与express-session请求匹配时,

 UPDATE session SET sid='O6rS2cPlQ6JDaUUxxYRAg-VI5MmldaRE' WHERE sid='qiQfhyAvDDPD7muJLtGdZudKqMug0aAC'; 

会话正确提取,用户持久:

 express-session fetching O6rS2cPlQ6JDaUUxxYRAg-VI5MmldaRE +3s express-session session found +2ms > deserializeUser with id: 1 Executing (default): SELECT "id", "nickname", "email", "password", "passwordHash", "lastLoggedIn", "createdAt", "updatedAt" FROM "users" AS "user" WHERE "user"."id" = 1; Authentication status: req.cookies: undefined req.isAuthenticated: true req.session: Session { cookie: { path: '/', _expires: 2017-09-30T10:55:31.514Z, originalMaxAge: 2592000000, httpOnly: true, secure: false }, passport: { user: 1 } } Logged in as "AntonAL" express-session saving O6rS2cPlQ6JDaUUxxYRAg-VI5MmldaRE +577ms express-session split response +1ms info: GET / 200 585ms statusCode=200, url=/, host=localhost:3000, accept-encoding=gzip, deflate, cookie=connect.sid=s%3AO6rS2cPlQ6JDaUUxxYRAg-VI5MmldaRE.M4iFzpVZP9fNa%2FLEomsMD8D9LjA1uFnDMnXT%2FHR3wyk; meteor_login_token=4YvVuK0V4adQJaMM2setEAx9_Ki7q6At19YfAvwyOJ8; _ga=GA1.1.1413606909.1501852025, connection=keep-alive, upgrade-insecure-requests=1, accept=text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8, user-agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/603.3.8 (KHTML, like Gecko) Version/10.1.2 Safari/603.3.8, referer=http://localhost:3000/user/login, cache-control=max-age=0, accept-language=ru, method=GET, httpVersion=1.1, originalUrl=/, , responseTime=585, user=AntonAL 

所以,现在清楚了 – sid参数是不同的,当生成会话并获取它时

       

网上收集的解决方案 "会话不能正确地从存储中获得,使用express-session和passportjs"

弄清楚了。

在客户端代码中,我使用下面的代码fetch函数:

 fetch('/user/login', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(values) }); 

这种方法给了我有问题的问题。

当我在路由中将请求方法更改为“GET”,并使用简单的redirect,我得到它的一切工作。

 window.location.href = "/login?"+querystring.stringify(values); 

为什么会发生?