2013-03-26 2 views
5

Я пытаюсь использовать redis с выражением, чтобы создать логин и сеанс пользователя. Я проверить маршрут с помощью этого завитка сценария:Node.js/express - использование паспорта с redis, получение сеанса неавторизованным

curl -d 'email=testEmail&password=testPass' http://localhost:3000/users/session 

Когда я делаю это, паспорт прекрасно работает через сериализацию, а затем возвращает HTTP 302. Я не понял, что он делает после сериализации, но когда я пытаюсь он в браузере с моей формой входа html вместо curl, он показывает мне «Unauthorized» 401, и я не вижу ни одного из моих консольных журналов. Вот мой app.js:

var express = require('express') 
    , fs = require('fs') 
    , cons = require('consolidate') 
    , http = require('http') 
    , flash = require('connect-flash') 
    , passport = require('passport') 
    , RedisStore = require("connect-redis")(express) //for sessions (instead of MemoryStore) 
    , redis = require('redis') 
    , env = process.env.NODE_ENV || 'development' 
    , config = require('./config/config')[env] 
    , db = redis.createClient(config.db.port, config.db.host); 

db.select(config.db.users) 
db.auth(config.db.auth); 

var app = express(); 

//require passport strategies (see code block below) 
require('./config/passport')(passport, config, app) 

app.use('/assets', express.static(__dirname + '/public')); 
app.use('/', express.static(__dirname + '/')); 
app.set('views', __dirname + '/views'); 
app.set('view engine', 'html'); 

app.configure(function(){ 
    app.set('config', config); 
    app.set('db', db); 
    app.set('port', process.env.PORT || 3000); 
    app.engine('.html', cons.swig); 
    app.use(express.logger('dev')) 
    app.use(express.favicon(__dirname + '/public/img/favicon.ico')); 
    app.use(express.cookieParser()) 
    app.use(express.bodyParser()) //enables req.body 
    app.use(express.methodOverride()) //enables app.put and app.delete (can also just use app.post) 
    app.use(express.session({ 
     secret: 'topsecret', 
     cookie: {secure: true, maxAge:86400000}, 
     store: new RedisStore({ 
      client:db, 
      secret:config.db.auth 
     }) 
    })); 

    app.use(flash()) 
    app.use(passport.initialize()) 
    app.use(passport.session()) 
    app.use(app.router) 
}); 

// Bootstrap routes 
require('./config/routes')(app, passport); 

http.createServer(app).listen(app.get('port'), function(){ 
    console.log("Express server listening on port " + app.get('port')+', mode='+env); 
}); 

И маршрут POST сессии:

app.post('/users/session', passport.authenticate('local', {successRedirect: '/', failureFlash: 'Invalid email or password.', successFlash: 'Welcome!'}), users.session); 

я мог только действительно найти примеры паспорта с MongoDB, так что я не уверен в следующем. Я пытаюсь найти пользователь, но я не уверен, что обратные вызовы или что паспорт делаю с информацией о пользователе, когда я возвращусь сделал:

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

     var db = app.get('db') 
     var multi = db.multi(); 

     db.get('email:'+email, function(err, uid){ 
      if (err) { console.log(err); return err } 
      if (!uid) { console.log('no uid found'); return null } 

      console.log('found '+uid) 
      db.hgetall('uid:'+uid, function(err, user){ 
       if (err) { console.log(err); return err } 
       if (!user) { 
        console.log('unkwn usr') 
        return done(null, false, { message: 'Unknown user' }) 
       } 

       if (password != user.password) { 
        console.log('invalid pwd') 
        return done(null, false, { message: 'Invalid password' }) 
       } 
       console.log('found user '+user) //I see this fine with curl, but no logs with browser 
       return done(null, user) 
      }); 
     });  
    } 
)) 

Паспорта сериализацию:

passport.serializeUser(function(user, done) { 
    console.log('passport serializing...'+user.name) 
    done(null, user.name) //no idea what happens to it after this. returns a 302 with curl, and 401 with browser 
}) 

Почему это действовать по-разному с браузером, чем с завитом? Любая помощь или комментарии очень ценятся!

+0

Разница заключается в том, что ваш браузер может отправлять куки-файлы (слева). Попробуйте запустить браузер в режиме инкогнито/приватный. Кроме того, вы реализуете 'passport.deserializeUser'? Если нет, вы должны. – robertklep

+0

Пробовал его с помощью режима инкогнито и удалял кеш/файлы cookie, те же результаты. Я до сих пор не дошел до того, что мне понадобится deserializeUser, я считаю, что это для удаления сеанса, правильно? Он по-прежнему показывает «Несанкционированный», когда я использую браузер, и ни один из моих консолей не отображается. –

ответ

1

Понял это! Чтобы использовать паспорт с любой базой данных (а не только монго), я бы порекомендовал сначала попробовать его с помощью фиктивного пользователя. Вот что я сделал.

Войти Форма (login.html):

<form method="post" action="http://localhost:3000/users/session" name="loginform"> 
    <input id="login_input_username" type="text" name="email" /> 
    <input id="login_input_password" type="password" name="password" autocomplete="off" /> 
    <input type="submit" name="login" value="Submit" /> 
</form> 

маршрутизации (route.js):

app.post('/users/session', passport.authenticate('local'), 
    function(req, res){ 
     res.end('success!'); 
    }); 

установка Локальная стратегия Паспорт (passport.js):

passport.use(new LocalStrategy({ usernameField: 'email', passwordField: 'password' }, 
    function(email, password, done) { 
     //find user in database here 
     var user = {id: 1, email:'test', password:'pass'}; 
     return done(null, user); 
    } 
)); 

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

passport.deserializeUser(function(id, done) { 
    //find user in database again 
    var user = {id: 1, email:'test', password:'pass'}; 
    done(null, user); 
}) 

Хотя мне интересно, нужно ли искать пользователя в моей базе данных дважды, или если я неправильно использую десериализацию.

+6

Цель 'serializeUser' - хранить в сеансе определенную форму идентификационной информации для пользователя; 'deserializeUser' использует эту информацию для повторной загрузки полной информации пользователя. Вы можете либо сохранить весь пользовательский объект в сеансе (так что вам не нужно снова запрашивать базу данных для него), либо сохранить идентификатор (в этом случае вам нужно запросить базу данных в 'deserializeUser', чтобы разрешить идентификатор к записи пользователя). Это зависит, хотя если пользовательский объект может храниться в сеансе как есть. – robertklep

+1

(также, если вы храните весь объект пользователя, он может отличаться от информации пользователя в базе данных, если это изменилось с тех пор, как последний раз данные пользователя были сериализованы в сеансе) – robertklep

+0

Хмм, если я запрашиваю базу данных для -serializing, и пользователь что-то изменил (скажем, имя своего профиля), тогда сериализованная версия файла cookie не будет соответствовать тому, что находится в db. Не означает ли это, что сессия будет недействительной (в последнем подходе)?и разве мы не хотим воздерживаться от запроса db на десериализацию? –

Смежные вопросы