2017-08-31 132 views
5

我正在使用passport,express-sessionconnect-pg-simple會話未正確從存儲中獲得,使用快速會話和passportjs

問題是,會話不正確地從存儲獲得,它正確地(我希望,但懷疑)得到保存。

我的設置與我在許多教程中找到的相同。

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('/'); 
    }); 
} 

有趣的部分是調試輸出 '表達會話',這要歸功於驚人的NPM-包debug

所以,當/user/login收到請求時,與用戶名= 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 

我看,這表達會話「試圖與另一SIDO6rS2cPlQ6JDaUUxxYRAg-VI5MmldaRE,但這來獲取會話t存在於數據庫中。

爲什麼會發生?

據我所知,應該通過SID = qiQfhyAvDDPD7muJLtGdZudKqMug0aAC取...

什麼問題可以與我的設置?

一個密鑰,「餅乾解析器」不使用,根據recomentation「注意由於版本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參數是不同的,當生成會話並提取它時

+0

如果使用'cookie-parser',行爲是否會改變? –

+0

@BrahmaDev,編號 – AntonAL

回答

0

想通了。

在客戶端代碼中,我用fetch功能與下面的代碼:

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

這種做法給了我所討論的問題。

當我在路由中將請求方法更改爲'GET'並使用簡單重定向時,我得到它的所有工作。

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

爲什麼會發生這種情況?

+0

您需要在提取中使用'credentials'選項來發送cookie。 https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch –

+0

檢查從客戶端發送的兩個請求中的標頭 –