【问题标题】:Server side routes in Iron Router and MeteorIron Router 和 Meteor 中的服务器端路由
【发布时间】:2015-02-27 03:49:20
【问题描述】:

转发

似乎在 Meteor 中,我们无法调用服务器端路由来将文件呈现到页面,而无需从我们的正常工作流程中获得某种解决方法,从我所读到的有关服务器端路由的信息中。我希望我错了,有一种简单的方法可以实现我想要做的事情......

**对不起,如果这有点长,但我认为在这种情况下提供更多背景和上下文是有保证的**

软件/版本

我正在使用最新的 Iron Router 1.* 和 Meteor 1.* 开始,我只使用帐户密码。

背景/上下文

我有一个 onBeforeAction,它只是根据用户是否登录将用户重定向到欢迎页面或主页:

both/routes.js

Router.onBeforeAction(function () {
  if (!Meteor.user() || Meteor.loggingIn())
    this.redirect('welcome.view');
  else
    this.next();
  }
  ,{except: 'welcome.view'}
);

Router.onBeforeAction(function () {
  if (Meteor.user())
    this.redirect('home.view');
  else
    this.next();
  }
  ,{only: 'welcome.view'}
);

在同一个文件both/routes.js 中,我有一个简单的服务器端路由,可以将pdf 呈现到屏幕上,如果我删除onBeforeAction 代码,该路由就可以工作(pdf 呈现到页面):

Router.route('/pdf-server', 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-server 时出现异常,同时保留 onBeforeAction 代码。

可以在此处找到有关异常的见解:SO Question on Exception

异常的解决方法

上述SO问题中答案的主要要点是"You use Meteor.user() in your Route.onBeforeAction but it has no access to this information",而何时,"your browser make a GET/POST request" [服务器端路由?],"to the server it doesn't have any information regarding the user's authentication state."

根据相同的 SO 回答者,解决方案是 "find an alternative way to authenticate the user,",一种方法是使用 "cookies'"

因此,在此之后,我找到了另一个 SO 答案(由与以前相同的回答者提供),此处概述了设置和获取 cookie 的方法:SO Cookies technique

** 因此,总而言之,为了允许服务器端路由,建议我使用 cookie 而不是 Meteor.userId() 或 this.userId 之类的东西。 **

添加Cookie相关代码

所以我在我的项目中添加了以下代码: 客户端/main.js

Deps.autorun(function() {
    if(Accounts.loginServicesConfigured() && Meteor.userId()) {
        setCookie("meteor_userid",Meteor.userId(),30);
        setCookie("meteor_logintoken",localStorage.getItem("Meteor.loginToken"),30);
    }
}); 

在我的服务器端路由中,我将路由更改为:

both/routes.js

Router.route('/pdf-server', function() {
  //Parse cookies using get_cookies function from : https://stackoverflow.com/questions/3393854/get-and-set-a-single-cookie-with-node-js-http-server
  var userId = get_cookies(req)['meteor_usserid'];
  var loginToken = get_cookies(req)['meteor_logintoken'];
  var user = Meteor.users.findOne({_id:userId, "services.resume.loginTokens.token":loginToken});
  var loggedInUser = (user)?user.username : "Not logged in";

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

但这并没有按预期工作,setCookie 代码由于某种原因无效。

我的问题

问题 1:以 SO Cookies technique 似乎对我不起作用,是这样吗 技术在 15 年仍然有效?

问题 2:使用 cookie,我如何通知服务器 基于这些 cookie 的身份验证状态?或者,另一种方式,如何在我的服务器中添加 cookie 检查 侧路由“通知”服务器有关用户的信息?我可以检查 这条路线上的任何东西;我可以拒绝任何用户,但不知何故 服务器需要“知道”用户登录对吗?

问题 3:cookie 是解决此问题的最佳方法,还是存在 实现相同目标的更简单方法?

附带问题:我见过一些使用中间件的地方 服务器端路由,例如:

WebApp.connectHandlers.stack.splice(...);

WebApp.connectHandlers.use(function(...) ...);

但是这些示例都没有内部安全性,将使用中间件 这样可以让我解决我的问题吗?

【问题讨论】:

  • Meteor 默认不包含 cookie 支持,因为 cookie 启用了大量的攻击向量,例如CSRF。不幸的是,服务器端路由无法访问身份验证信息,因此您只能设计一个系统,您认为该系统足以证明用户就是他们所说的那个人。这通常采用某种令牌或密钥的形式。该密钥可以存储在 cookie 中,但并非必须如此。
  • 在您的特定用例中,pdf-server 路由是否需要知道哪个用户正在发出请求,或者任何经过身份验证的用户就足够了?
  • 大卫,不,这是我真正不完全理解的部分之一。我没有告诉服务器它需要对该路由的用户进行身份验证。不知何故,onBeforeAction 是我采用 pdf-server 路由时引发错误的代码。所以我想,当采用服务器端路由时,首先调用 onBeforeAction,并尝试检查 Meteor.user(),并且由于它是服务器端路由,因此没有 Meteor.user(),所以它会抛出。在客户端,使用 onBeforeAction,路由很好,因为 Meteor.user() 存在那里。
  • 所以,我猜我应该设置 cookie(上面的 cookie 代码现在不起作用)并在 onBeforeAction 而不是 Meteor.user() 中检查它...
  • 哦,我现在看到了混乱的根源。我会添加一个答案,但我们可能需要一起迭代它才能让某些东西发挥作用。

标签: javascript node.js cookies meteor iron-router


【解决方案1】:

您的服务器端路由正在运行全局 onBeforeAction 代码(它在共享目录中定义),因为服务器路由是简单的 REST 端点,它不理解用户身份验证信息(即 Meteor.user() 不理解)不工作)。解决方案是使用Meteor.isClient 包装特定于客户端的onBeforeAction 调用,或者只是将该代码移动到client 目录下。例如:

if (Meteor.isClient) {
  Router.onBeforeAction(function () {
    if (!Meteor.user() || Meteor.loggingIn())
      this.redirect('welcome.view');
    else
      this.next();
    }
    ,{except: 'welcome.view'}
  );

  Router.onBeforeAction(function () {
    if (Meteor.user())
      this.redirect('home.view');
    else
      this.next();
    }
    ,{only: 'welcome.view'}
  );
}

Router.route('/pdf-server', function() {
  ...
}, {where: 'server'});

【讨论】:

  • 太好了,这行得通!现在剩下的就是确保访问文件的用户实际上是经过身份验证的吗?
  • 我想我应该为服务器端路由身份验证的狭隘问题添加另一个 SO 问题?就像 API 安全 - 最佳实践部分中的 cookie 或技术一样:meteorpedia.com/read/REST_API?
  • 太棒了!好的,我们解决了第一部分,所以也许接受这个答案并打开一个新的。新问题不应该提供所有背景信息——只是简单地询问在服务器端路由中对用户进行身份验证的最佳方式。我只是删除你的另外两个未解决的问题,因为它们现在不太相关。
  • 关于服务器端路由身份验证的 SO 问题发布在这里:stackoverflow.com/questions/27734110/…
猜你喜欢
  • 2013-09-03
  • 1970-01-01
  • 2014-03-27
  • 2015-03-14
  • 1970-01-01
  • 2018-03-20
  • 2016-08-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多