【问题标题】:Exception when using a server route and onBeforeAction使用服务器路由和 onBeforeAction 时出现异常
【发布时间】:2015-02-25 21:32:48
【问题描述】:

我在尝试添加 pdf 文件生成时看到了奇怪的行为。

以下代码在 if 语句中抛出: 都\routes.js

Router.onBeforeAction(function () {   if (!Meteor.user() || Meteor.loggingIn()) {
    this.redirect('welcome.view');   }   else {
    Meteor.call("userFileDirectory", function (error, result) {
      if (error)
        throw error;
      else
        console.log(result);
 });
    this.next();   } }, {   except: ['welcome.view'] });

错误:Meteor.userId 只能在方法调用中调用。采用 发布函数中的 this.userId。在 Object.Meteor.userId (packages/accounts-base/accounts_server.js:19:1) 在 Object.Meteor.user (packages/accounts-base/accounts_server.js:24:1) 在 [object 对象].Router.onBeforeAction.except (app/both/3-router/routes.js:10:15) 在 packages/iron:router/lib/router.js:277:1 at [object 对象]._.extend.withValue (packages/meteor/dynamics_nodejs.js:56:1) 在 [object Object].hookWithOptions (packages/iron:router/lib/router.js:276:1) 在 boundNext (packages/iron:middleware-stack/lib/middleware_stack.js:251:1) 在 runWithEnvironment (packages/meteor/dynamics_nodejs.js:108:1) 在 packages/meteor/dynamics_nodejs.js:121:1 at [object Object].dispatch (packages/iron:middleware-stack/lib/middleware_stack.js:275:1)

仅当我将此代码添加到文件中时,才会采用 /pdf 路由:

Router.route('/pdf', function() {
  var filePath = process.env.PWD + "/server/.files/users/test.pdf";
  console.log(filePath);
  var fs = Npm.require('fs');
  var data = fs.readFileSync(filePath);
  this.response.write(data);
  this.response.end();
}, {
  where: 'server'
});

上面的代码工作正常;当我取出 onBeforeAction 代码时,pdf 被渲染到屏幕上并且没有抛出异常。

反之亦然,如果我取出服务器路由,就没有路由会导致异常。

【问题讨论】:

    标签: javascript node.js meteor iron-router


    【解决方案1】:

    这是因为您使用的路由是服务器端路由。 Meteor 用来验证用户的技术是通过 DDP 协议,通过 websockets 完成的。

    当您的浏览器向服务器发出GET/POST 请求时,它没有任何关于用户身份验证状态的信息。

    您在Route.onBeforeAction 中使用了Meteor.user(),但它无权访问此信息。

    解决方案是找到一种替代方法来验证用户身份。一种这样的方法是使用 cookie。

    这是 Meteor 身份验证系统的已知问题,请参阅:https://github.com/EventedMind/iron-router/issues/649

    【讨论】:

    • 我在这里读到了你的 SO 答案:stackoverflow.com/questions/16727922/…,我现在可以使用这个过程(写于 13 年)吗?如果是这样,我会将 cookie 检查代码放在 onBeforeAction 方法中还是服务器端路由中?
    • 我想你回答了为什么,大卫韦尔登在这里回答了如何解决它:stackoverflow.com/questions/27714618/…
    • 我的意思是,问题是关于异常的,根据 David Weldon 的回答,异常是固定的......但是服务器端身份验证系统/方法仍然需要制定(是您答案的一部分,但没有完全回答问题)...再次,您确实回答了它发生的原因,但仅在身份验证方面。
    • 我会在这里给你答案(只是上面提到的警告)。然而,作为后续,关于服务器端路由和身份验证的 SO 问题在这里:stackoverflow.com/questions/27734110/…
    【解决方案2】:

    比 cookie 更好的方法可能是存储 userId 和一些 sessionId 的 Meteor 命名集合:

    您可以在调用服务器之前将当前的 userId 存储在客户端:

    var sessionId = Random.id(); 
    col = new Mongo.Collection('session');
    col.insert({
      sessionId: sid,
      userId: Meteor.userId(),
      issued: new Date()
    });
    

    然后通过GET/POST请求将sessionId传递给服务器,并在服务器上读取:

    var sid = this.request.query.sid;
    var user = col.findOne({sessionId: sid}); // returns an object
    

    使用单独的参数比使用 userId 本身要好,因为您可以在一段时间后或在服务器调用后立即撤销此 sessionId

    需要适当的allow/deny 权限才能防止任何人更新集合。另外,请注意您不能信任客户端的new Date()

    【讨论】:

    • 谢谢。但是你能谈谈为什么这是一个更好的方法吗?
    • 此任务的代码似乎错误,因为我们可能有很多用户,对此深表歉意!
    • 流星集合是一种安全且反应性的方式,用于了解用户是否仍然经过身份验证/授权执行某项操作。饼干不是。但是上面的代码不起作用(我们必须在客户端和服务器上都使用一些 ID 来引用我们重复的 userId 存储在集合中。
    • 您说您发布的答案无效且不正确,但您将其发布为答案?对不起,我很困惑。你会发布一个“正确”、反应性、使用集合并且也在服务器上工作的答案吗?
    • “流星集合是一种安全且被动的方式,可以了解用户是否仍然经过身份验证/授权执行某项操作”...但这几乎是重点——在服务器端路由上不知道用户是谁。我如何在不知道谁在拉动的情况下从集合中拉动?我只是不明白,我认为代码会有所帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多