2013-03-26 17 views
5

Tôi đang cố gắng sử dụng redis with express để tạo đăng nhập và phiên người dùng. Tôi kiểm tra các tuyến đường sử dụng kịch bản curl này:Node.js/express - sử dụng hộ chiếu có redis, nhận phiên không được phép

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

Khi tôi làm điều này, hộ chiếu hoạt động tốt qua serialization, và sau đó nó sẽ trả về http 302. Tôi đã không tìm ra những gì nó làm sau khi serialization, nhưng khi tôi cố gắng nó trong trình duyệt với biểu mẫu html đăng nhập của tôi thay vì curl, Nó cho tôi thấy "Trái phép" 401 và tôi không thấy bất kỳ nhật ký bảng điều khiển nào của mình. Dưới đây là app.js tôi:

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); 
}); 

Và con đường phiên POST:

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

tôi chỉ có thể thực sự tìm thấy ví dụ về hộ chiếu với MongoDB, vì vậy tôi không chắc chắn về những điều sau đây. Tôi cố gắng để tìm thấy một người sử dụng, nhưng tôi không chắc chắn về callbacks hoặc những gì hộ chiếu đang làm với thông tin người dùng khi tôi trở về thực hiện:

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 serialization:

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 
}) 

Tại sao thực hiện điều này hành động khác với trình duyệt so với curl? Bất kỳ trợ giúp hoặc nhận xét nào được đánh giá cao!

+0

Sự khác biệt là trình duyệt của bạn có thể đang gửi cookie phiên (trái). Thử chạy trình duyệt của bạn ở chế độ Ẩn danh/Riêng tư. Ngoài ra, bạn có thực hiện 'passport.deserializeUser' không? Nếu không, bạn nên. – robertklep

+0

Đã thử với chế độ ẩn danh và bộ nhớ cache/cookie đã xóa, cùng một kết quả. Tôi đã không đến mức mà tôi cần deserializeUser, tôi tin rằng đó là để loại bỏ phiên, đúng không? Nó vẫn hiển thị "Không được phép" khi tôi sử dụng một trình duyệt và không có console.log nào của tôi hiển thị. –

Trả lời

1

Đã tìm ra! Để sử dụng hộ chiếu với bất kỳ cơ sở dữ liệu nào (không chỉ mongo), tôi khuyên bạn nên dùng thử với người dùng giả trước. Đây là những gì tôi đã làm.

Login Form (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> 

Routing (route.js):

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

Passport Chiến lược địa phương thiết lập (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); 
}) 

Mặc dù tôi tự hỏi nếu nó cần thiết để tìm người dùng trong cơ sở dữ liệu của tôi hai lần, hoặc nếu tôi đang sử dụng deserialize không chính xác.

+6

Mục đích của 'serializeUser' là lưu trữ một số dạng thông tin nhận dạng cho người dùng trong phiên làm việc; 'deserializeUser' sử dụng thông tin đó để lấy lại toàn bộ thông tin người dùng. Bạn có thể lưu trữ toàn bộ đối tượng người dùng trong phiên làm việc (vì vậy bạn không phải truy vấn lại cơ sở dữ liệu), hoặc lưu trữ một id (trong trường hợp này bạn cần truy vấn cơ sở dữ liệu trong 'deserializeUser' để giải quyết id vào hồ sơ người dùng). Nó phụ thuộc mặc dù nếu đối tượng người dùng có thể được lưu trữ trong phiên làm việc. – robertklep

+1

(ngoài ra, nếu bạn lưu trữ toàn bộ đối tượng người dùng, nó có thể khác với thông tin người dùng trong cơ sở dữ liệu nếu thông tin đó đã thay đổi kể từ lần cuối cùng dữ liệu của người dùng được tuần tự hóa vào phiên) – robertklep

+0

Hmm, nếu tôi truy vấn cơ sở dữ liệu cho -serializing, và người dùng đã thay đổi một cái gì đó (nói tên hồ sơ của họ), sau đó phiên bản cookie serialized sẽ không phù hợp với những gì trong db. Vì vậy, không có nghĩa là phiên sẽ không hợp lệ (trong cách tiếp cận sau)?và chúng tôi sẽ không muốn từ chối truy vấn db trên deserialize? –