2014-07-22 35 views
4

我正在使用passport.js + passport-facebook-token来保护我的API构建与Strongloop的Loopback Framework。为什么每次请求都执行passport.serializeUser?

为什么护照在成功反序列化后再次序列化反序列化的用户?每次请求都会调用passport.authenticate方法!我究竟做错了什么?

这里是节点的日志:

deserializeUser, id: XXXXXXXXXXXXXXXX 
User found. 
serializeUser, id: XXXXXXXXXXXXXXXX 
GET /api/events?access_token=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 304 182ms 

这里是js代码:

passport.use(new FacebookTokenStrategy({ 
    clientID: XXXXXXXXXXXXXXXX, 
    clientSecret: 'XXXXXXXXXXXXXXXXXXXXXXXXXXXX' 
    }, 
    function(accessToken, refreshToken, profile, done) { 
    //check user table for anyone with a facebook ID of profile.id 
    User.findOne({ 
     'facebookId': profile.id 
    }, function(err, user) { 
     if (err) { 
     return done(err); 
     } 
     if (user) { 
     console.log("User found."); 
     return done(err, user); 
     } else { 
     console.log("User not found."); 
     User.create({ 
      email: profile.emails[0].value, 
      facebookId: profile.id, 
      password: 'secret' 
     }, function(err, user) { 
      console.log(user.id); 
      console.log(user.email); 
      console.log(user.facebookId); 
      console.log("User created"); 
      return done(err, user); 
     }); 
     } 
    }); 
    })); 

passport.serializeUser(function(user, done) { 
    console.log('serializeUser, id: ' + user.facebookId); 
    done(null, user.facebookId); 
}); 

passport.deserializeUser(function(id, done) { 
    console.log('deserializeUser, id: ' + id); 
    User.findOne({ 
    'facebookId': id 
    }, function(err, user) { 
    if (!err) { 
     done(null, user); 
    } else { 
     done(err, user); 
    } 
    }); 
}); 
+1

你可以在哪里定义处理认证的中间件的代码? 它应该看起来像'passport.authenticate(“facebook”,function ....)'。 如果你做了'app.get(“/ *”,passport.authenticate())'',它就像预期的那样工作。 –

+0

这是为此添加的唯一loc:app.use(passport.authenticate('facebook-token')); –

+0

嗯,好吧,我明白了。但我的理解是,它应该被添加为中间件,因为它可以保护我的API免受未经授权的访问......哪里可以添加此行?或者你有什么建议? –

回答

7

关于你为什么passport.authenticate叫做在每次请求的问题,那是因为你把它定义为一个中间件,可能在任何路由逻辑发生之前。

如果您对您的应用程序的私人公共部分,你可以做这样的事情:

// Define a specific that will handle authentication logic 
app.get("/auth", passport.authenticate('facebook-token',function(){...}); 

// Public sections which do not require authentication 
app.get("/public1",...); 
app.post("/public2",...); 

// Private sections which do require authentication 
app.get("/private1", function(req,res,next){ 
    if (req.isAuthenticated()){ // Check if user is authenticated 
     // do things... 
    }else{ // Wow, this guy is not authenticated. Kick him out of here ! 
     res.redirect("/auth"); 
    } 
}); 

现在,如果你有多个私人的部分,你可能会发现它有点tidious到为每个私人部分做同样的事情。 您可以定义一个自定义函数来检查用户是否已通过身份验证,并允许请求继续进行。 喜欢的东西

function isThisGuyAuthenticated(req,res,next){ 
    if (req.isAuthenticated()){ 
     return next(); // Ok this guy is clean, please go on ! 
    }else{ 
     res.redirect("/auth"); // This guy is shady, please authenticate ! 
    } 
} 

而且使用它像:现在

app.get("/private1",isThisGuyAuthenticated, doCrazySecretStuff); // doCrazySecretStuff will not be called if the user is not authenticated 
app.get("/private2", isThisGuyAuthenticated, getCocaColaRecipe); 
app.get("/private3", isThisGuyAuthenticated, flyToMars); 
app.get("/public", showInfo); // showInfo will be called whether the user is authenticated or not 

,如果您的应用程序只有私人的部分,你能避免它定义为中间件重复到isThisGuyAuthenticated通话(但不是通过定义passport.authenticate本身作为中间件!);

// Endpoint that will be hit is the user is redirected to /auth 
// BEWARE it needs to be above the middleware, otherwise you'll end up with an infinite redirection loop 
app.get("/auth", passport.authenticate('facebook-token',function(){...}); 

// Middleware that will be called on every request 
app.use(isThisGuyAuthenticated); 

// You app's endpoints 
app.get("/private1", doCrazySecretStuff); // doCrazySecretStuff will not be called if the user is not authenticated 
app.get("/private2", getCocaColaRecipe); 
app.get("/private3", flyToMars); 

这是明确的吗?

编辑:我错误地把中间件放在“/ auth”端点之前。确保它被放置在

+0

非常好的答案!非常感谢,我认为现在很清楚,让我试试看,我会将它作为答案来检查! –

+1

不客气。如果您有任何问题,请告诉我。请检查我的编辑,我最初犯了一个可怕的错误。 –

+0

没错。我在/ auth函数中修复了一个小错字...!但它的工作。现在只有第一个请求/ auth需要〜200ms的其他请求,它利用了现有的会话,并且非常快速(<10ms):) THX –

相关问题