使用服务器路由和之前操作时出现异常

Exception when using a server route and onBeforeAction

本文关键字:操作 异常 服务器 路由      更新时间:2023-09-26

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

在 if 语句上,以下代码引发:两者''路由.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 in publish functions.at Object.Meteor.userId (packages/accounts-base/accounts_server.js:19:1) at Object.Meteor.user (packages/accounts-base/accounts_server.js:24:1) at [object 对象]。Router.onBeforeAction.except (应用程序/两者/3 路由器/路由.js:10:15) 在 packages/iron:router/lib/router.js:277:1 at [object Object]._.extend.withValue (packages/meteor/dynamics_nodejs.js:56:1) at [object Object].hookWithOptions (packages/iron:router/lib/router.js:276:1) at boundNext (packages/iron:middleware-stack/lib/middleware_stack.js:251:1) at runWithEnvironment (packages/meteor/dynamics_nodejs.js:108:1) at packages/meteor/dynamics_nodejs.js:121:1 at [object Object].dispatch (包/熨斗:中间件堆栈/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'
});

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

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

发生这种情况是因为您使用的路由是服务器端路由。Meteor用于验证用户身份的技术是通过DDP协议通过websockets完成的。

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

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

对此的解决方案是找到一种对用户进行身份验证的替代方法。其中一种方法是使用cookie的。

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

比 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()