2014-07-26 20 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