2014-07-26 19 views
3

我试图获取当前用户的问题,像这样的请求:为什么sails.js,Angular.js和Passport.js中的套接字请求的`req.user`未定义?

http://localhost:1337/question/forme 

由于GET请求的一部分,我访问时,它是能够访问req.user.username和服务JSONresponse从浏览器。

当我尝试从我的Angular client.js文件发出同样的Socket.get()请求时,它不起作用。我也尝试使用浏览器控制台访问它,并且失败了socket.get()请求。

回答

7

我花了大量的时间搞清楚所有的运动部件,以获得护照带帆的工作对我blog

我会重新发布下面的相关部分,另外还有政策的变化我做了。

我创建了一个passport.js文件来管理我的护照配置/策略登记

/config/passport.js 

var passport = require('passport'), 
LocalStrategy = require('passport-local').Strategy; 

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

passport.deserializeUser(function(id, done) { 
    User.findOneById(id).done(function (err, user) { 
     done(err, user); 
    }); 
}); 

passport.use(new LocalStrategy({ 
     usernameField: 'email', 
     passwordField: 'password' 
    }, 
    function(email, password, done) { 
    User.findOne({ email: email}).done(function(err, user) { 
      if (err) { return done(err); } 
      if (!user) { return done(null, false, { message: 'Unknown user ' + email }); } 
      if (user.password != password) { return done(null, false, { message: 'Invalid password' }); } 
      return done(null, user); 
     }); 
    } 
)); 

然后我用了一个政策,以验证身份验证。如果发出套接字请求,它将使用护照会话。

/api/policies/isAuthenticated.js 
module.exports = function(req, res, next) { 

    // User is allowed, proceed to the next policy, 
    // or if this is the last policy, the controller 
    // Sockets 
    if(req.isSocket) 
    { 
     if(req.session && 
      req.session.passport && 
      req.session.passport.user) 
     { 
      //Use this: 

      // Initialize Passport 
      sails.config.passport.initialize()(req, res, function() { 
       // Use the built-in sessions 
       sails.config.passport.session()(req, res, function() { 
        // Make the user available throughout the frontend 
        //res.locals.user = req.user; 
        //the user should be deserialized by passport now; 
        next(); 
       }); 
      }); 

      //Or this if you dont care about deserializing the user: 
      //req.user = req.session.passport.user; 
      //return next(); 

     } 
     else{ 
      res.json(401); 
     } 


    } 
    else if (req.isAuthenticated()) { 
     return next(); 
    } 
    else{ 
     // User is not allowed 
     // (default res.forbidden() behavior can be overridden in `config/403.js`) 
     return res.redirect('/account/login'); 
    } 
}; 
0

风帆的优点在于,它以与HTTP请求相同的方式路由套接字请求,因此您可以使用任一传输命中相同的端点并执行相同的代码。但是,有限制,你在这里看到一个。 Passport是Express中间件,并且套接字请求未被Express处理,所以中间件不适用。

我护照上没有专家,但我想它仍然有效使用会话,这提供给您的插座的要求,所以我觉得你很可能在以下两种方式之一处理这个问题:

  1. 从您的控制器操作中的底层会话变量中读取用户名
  2. 使用策略在req对象尚未可用时(即对于非HTTP请求)应用“用户”。
1

您可以将认证方法注入到套接字请求中。因为这只是让一点点劫持到config/bootstrap.js

var passport = require('passport'), 
http = require('http'), 
initialize = passport.initialize(), 
session = passport.session(), 
methods = ['login', 'logIn', 'logout', 'logOut', 'isAuthenticated', 'isUnauthenticated']; 

module.exports.bootstrap = function(cb) { 
    sails.removeAllListeners('router:request'); 
    sails.on('router:request', function(req, res) { 
     initialize(req, res, function() { 
      session(req, res, function(error) { 
       if (error) { 
        return sails.config[500](500, req, res); 
       } 
       for (var i = 0; i < methods.length; i++) { 
        req[methods[i]] = http.IncomingMessage.prototype[methods[i]].bind(req); 
       } 
       sails.router.route(req, res); 
      }); 
     }); 
    }); 

    cb(); 
}; 

这种劫持您可以使用isAuthenticated()和护照等方法在插座后。

然后通过像Scott说的策略注入用户变量。

+0

这很聪明,但解除内部Sails事件如'router:request'不是很好的做法;将它们视为私人API。如果未来核心路由器的实施发生变化,这将会中断。能够通过套接字登录/登出可能并不重要,这也是我可以考虑使用套接字进行套接字的唯一原因,但是如果您真的想要更好的地方将在策略中,或者“之前“在[自定义钩子]路线(https://github.com/balderdashy/sails-docs/blob/master/concepts/extending-sails/Hooks/customhooks.md)(确保检查req.isSocket)。 – sgress454

+0

我知道这是不好的做法,但我真的需要护照与套接字配合使用。我发现只有这个解决方案可以帮助我。你的想法与自定义钩很好,谢谢:) – ghaiklor

+0

看到[这里](https://github.com/kasperisager/sails-generate-auth/issues/11#issuecomment-49125634)为例在政策中做。 – sgress454