Javascript Iron路由器和Meteor中的服务器端路由 向前地

Javascript Iron路由器和Meteor中的服务器端路由 向前地,javascript,node.js,cookies,meteor,iron-router,Javascript,Node.js,Cookies,Meteor,Iron Router,在Meteor中,我们似乎无法调用服务器端路由来将文件呈现到页面,而无需从我们的正常工作流程中进行某种变通,正如我所读到的服务器端路由。我希望我在这一点上是错的,有一个简单的方法来实现我期待的目标 **抱歉,如果这有点长,但我认为在这种情况下,提供更多的背景和背景是有必要的** 软件/版本 我正在使用最新的Iron Router 1.*和Meteor 1.*并且首先,我只使用帐户密码 背景/背景 我有一个onBeforeAction,它可以根据用户是否登录将用户重定向到欢迎页面或主页: 都是/r

在Meteor中,我们似乎无法调用服务器端路由来将文件呈现到页面,而无需从我们的正常工作流程中进行某种变通,正如我所读到的服务器端路由。我希望我在这一点上是错的,有一个简单的方法来实现我期待的目标

**抱歉,如果这有点长,但我认为在这种情况下,提供更多的背景和背景是有必要的**

软件/版本 我正在使用最新的Iron Router 1.*和Meteor 1.*并且首先,我只使用帐户密码

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

都是/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'}
);
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'});
在同一个文件/routes.js中,我有一个简单的服务器端路由,可以将pdf呈现到屏幕上,如果我删除onBeforeAction代码,该路由就会工作(pdf呈现到页面):

服务器路由上引发异常 这无关紧要,但是当我将上面的服务器端路由添加到文件并使用route/pdf服务器,同时保留onBeforeAction代码时,我遇到了一个异常

有关此异常的详细信息,请参见:

例外情况的解决办法 上述SO问题答案的主要要点是
“您在Route.onBeforeAction中使用Meteor.user(),但它无法访问此信息”
,并且当
“您的浏览器向服务器发出GET/POST请求”
[服务器端路由?],
“它没有关于用户身份验证状态的任何信息。”

根据相同的SO答案,解决方案是
“找到另一种验证用户身份的方法”
,其中一种方法是使用
“cookies”

因此,接下来,我发现了另一个So答案(由与之前相同的回答者提供),这里概述了设置和获取cookie的方法:

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

添加了Cookie相关代码 因此,我在我的项目中添加了以下代码: client/main.js

Deps.autorun(function() {
    if(Accounts.loginServicesConfigured() && Meteor.userId()) {
        setCookie("meteor_userid",Meteor.userId(),30);
        setCookie("meteor_logintoken",localStorage.getItem("Meteor.loginToken"),30);
    }
}); 
在我的服务器端路由中,我将路由更改为:

都是/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'}
);
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:以中描述的方式设置/获取cookie 似乎对我不起作用,是吗 技术在15年还有效吗

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

问题3:饼干是解决这一问题的最佳方式,还是存在一个 实现同样目标的更简单方法

附带问题:我已经看到一些地方使用了中间件 服务器端路由,例如:

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'});
但是这些例子中没有一个内部具有安全性,将使用中间件 这样能让我绕过我的问题吗


您的服务器端路由正在运行全局
onBeforeAction
代码(它在共享目录中定义),这会中断,因为服务器路由是不理解用户身份验证信息的简单REST端点(即
Meteor.user()
不起作用)。解决方案是将特定于客户端的
onBeforeAction
调用与
Meteor.isClient
包装在一起,或者简单地将该代码移动到
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'});

Meteor默认情况下不包括cookie支持,因为cookie支持大量攻击向量,例如。不幸的是,服务器端路由无法访问身份验证信息,因此您只能设计一个系统,该系统足以证明用户就是他们所说的用户。这通常采取某种令牌或密钥的形式。该密钥可以存储在cookie中,但不必存储在cookie中。在您的特定用例中,
pdf服务器
路由是否需要知道是哪个用户发出请求,或者任何经过身份验证的用户是否足够?David,不,这是我真正不完全理解的部分之一。我还没有告诉服务器它需要对该路由的用户进行身份验证。不知何故,onBeforeAction是在我使用pdf服务器路由时抛出错误的代码。因此,我假设,当采取服务器端路由时,首先调用onBeforeAction,并尝试检查Meteor.user(),因为它是服务器端路由,所以没有Meteor.user(),所以它抛出。在客户端,使用onBeforeAction时,路由很好,因为Meteor.user()存在。因此,我猜我应该设置cookie(上面的cookie代码现在不起作用)并在onBeforeAction中检查,而不是Meteor.user()…哦,我现在看到了混乱的根源。我将添加一个答案,但我们可能需要一起迭代才能使某些东西起作用。太好了,这很有效!现在剩下的就是确保访问文件的用户实际上已经通过了身份验证,对吗?我想我应该为服务器端路由的身份验证这个狭隘的问题添加另一个SO问题?就像来自API安全-最佳实践部分的cookie或技术:?太棒了!好的,我们解决了第一部分,所以也许可以接受这个答案并打开一个新的答案。新的问题不应该给出所有的背景信息——只需简单地询问在服务器端路由中对用户进行身份验证的最佳方法即可。我将删除您的另外两个开放性问题,因为它们现在不太相关。关于服务器端路由身份验证的SO问题发布在此处: