Sails.js + Passport.js 通过 websockets 进行身份验证

Posted

技术标签:

【中文标题】Sails.js + Passport.js 通过 websockets 进行身份验证【英文标题】:Sails.js + Passport.js authentication through websockets 【发布时间】:2013-06-26 06:29:32 【问题描述】:

当我将 Sails.js 与 Passport.js 一起使用时,当通过 websocket 请求时,req 对象上不存在 isAuthenticated 方法。

谁能告诉我为什么会这样?

【问题讨论】:

【参考方案1】:

或者,您可以劫持 'router:request' 事件以插入通行证以进行套接字请求。我在 'config/bootstrap.js' 中执行此操作:

module.exports.bootstrap = function (cb) 

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

  sails.removeAllListeners('router:request');
  sails.on('router:request', function(req, res) 
    initialize(req, res, function () 
      session(req, res, function (err) 
        if (err) 
          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();
;

使用这种方法,您不需要特殊处理来检查策略中的套接字请求身份验证。您仍然需要通过快速中间件为非套接字请求连接护照。

【讨论】:

我的问题是 PUT 和 POST 请求需要身份验证,只有 @xdissent 的回答解决了它。 这是一个很好的解决方法——这就是为什么,来自FAQ in lib/router: > + 当一个 HTTP 请求到达服务器时,它会在到达 Express 路由器之前到达 Sails 路由器吗? > + 不,它只命中 Express 路由器。 > > + OK.. Sails 路由器有什么请求? > + 向其他没有自己的路由器的附加服务器的请求,例如Socket.io 解释器将访问 Sails 路由器的通配符处理程序,然后它将与连接的服务器通信并模拟适当的路由。 这非常有效。它甚至允许我通过 Websockets 进行身份验证,因此我不必使用 XHR 请求。在套接字模式下的 req 缺少一些特定于表达的东西,它是前面提到的中间件。 只是好奇,return sails.config[500](500, req, res); 行在做什么?在 Sails 0.10.x 下,现在应该是 return serverError(); 在 Sails 0.11 中,socket 服务器已经升级。关于如何使用 Socket.IO 1.0 的任何指针?【参考方案2】:

请尝试检查 req.session.passport.user。 登录时它将包含用户信息,否则将未定义。 适用于任何类型的请求。

我认为这是因为在 WebSocket 请求的情况下,“req”实际上是假请求对象。它创建并直接传递给 Express 的路由器,绕过所有 Express 的中间件,包括 Passport 的中间件

【讨论】:

完全正确 - 有关其在 Sails 核心中的工作原理的说明,请查看 README in lib/router。这可能会在未来版本的 Sails 中得到简化——但首先要弄清楚其他一些注意事项(有关更多信息,请参阅 issue #141) 虽然这解决了“已登录问题”,但我如何访问实际的用户对象。使用普通的 http 护照正在运行反序列化用户功能,我可以从 req.user 访问它。现在有了套接字连接,我没有得到任何用户对象。【参考方案3】:

@ataman 完全正确。您使用 express.customMiddleware 配置安装的 Express 中间件仅适用于 Express HTTP 请求。

要让护照适用于所有请求,请在您的政策中使用它:

// e.g. 
// config/policies.js
module.exports = 
  SomeController: 
    someaction: function somePassportMiddlewareFn() 
  
;

【讨论】:

【参考方案4】:

另一种使用护照定义的方法登录、注销、...来扩展socket.io req的方法是重写策略或中间件,如下所示

module.exports = (req, res, next) ->
    if req.isSocket
        req = _.extend req, _.pick(require('http').IncomingMessage.prototype, 'login', 'logIn', 'logout', 'logOut', 'isAuthenticated', 'isUnauthenticated')
    middleware = passport.authenticate('bearer',  session: false )
    middleware(req, res, next)

【讨论】:

这段代码有文件名吗?如果是这样,该文件将存在于哪个目录中?

以上是关于Sails.js + Passport.js 通过 websockets 进行身份验证的主要内容,如果未能解决你的问题,请参考以下文章

Sails.js + Passport.js 获取当前登录用户

passport.js 使用sails.js 验证弹出窗口

使用 Passport.js 和 Sails.js 注册后如何重定向到特定位置?

Sails.js 0.11 和护照:“缺少凭据”错误

Passport.js 在 req.login 上失败

登录时如何“记住”用户-passport.js-phonegap