Exception when using a server route and onBeforeAction

我与影子孤独终老i 提交于 2019-11-30 10:01:31

问题


I'm seeing strange behavior when trying to add pdf file generation.

The following code, on the if statement, throws: both\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'] });

Error: Meteor.userId can only be invoked in method calls. Use 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 Object].Router.onBeforeAction.except (app/both/3-router/routes.js:10:15) at 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 (packages/iron:middleware-stack/lib/middleware_stack.js:275:1)

Only when I add this code into the file, and the /pdf route is taken:

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'
});

The above code works fine; the pdf is rendered to the screen and no exception is thrown, when I take out the onBeforeAction code.

The opposite is also true, if I take out the server route, there is no route that causes an exception.


回答1:


This occurs because the route you're using is a server side route. The technique Meteor uses to authenticate a user is done via the DDP protocol, over websockets.

When your browser makes a GET/POST request to the server it doesn't have any information regarding the user's authentication state.

You use Meteor.user() in your Route.onBeforeAction but it has no access to this information.

The solution to this is find an alternative way to authenticate the user. One such method is to use cookie's.

This is known issue with Meteor's authentication system, see: https://github.com/EventedMind/iron-router/issues/649




回答2:


A better way than cookies could be a named collection of Meteor that stores userId and some sessionId:

You can store current userId on the client side before the call to the server:

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

And then pass sessionId to the server through a GET/POST request and read it on the server:

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

Using a separate parameter is better than using userId itself because you can revoke this sessionId after some time or immediately after the server call.

Proper allow/deny permissions are required to prevent anyone from updating the collection. Also, please note that you can't trust new Date() on the client's side.



来源:https://stackoverflow.com/questions/27693247/exception-when-using-a-server-route-and-onbeforeaction

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!