Iron Router 和 Meteor 中的服务器端路由 [英] Server side routes in Iron Router and Meteor

查看:23
本文介绍了Iron Router 和 Meteor 中的服务器端路由的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

前进

似乎在 Meteor 中,我们无法调用服务器端路由来将文件呈现到页面,而没有我们正常工作流程中的某种解决方法,从我读到的关于服务器端路由的内容来看.我希望我对此是错的,并且有一种简单的方法可以实现我想要做的......

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

软件/版本

我使用的是最新的 Iron Router 1.* 和 Meteor 1.*,一开始,我只使用了帐户密码.

背景/背景

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

both/routes.js

Router.onBeforeAction(function () {if (!Meteor.user() || Meteor.loggingIn())this.redirect('welcome.view');别的this.next();},{除了:'welcome.view'});Router.onBeforeAction(function () {如果(流星.用户())this.redirect('home.view');别的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";控制台日志(文件路径);var fs = Npm.require('fs');var data = fs.readFileSync(filePath);this.response.write(data);this.response.end();}, {where: 'server'});

在服务器路由上抛出异常

这无关紧要,但是当我将上述服务器端路由添加到文件并采用路由/pdf-server,同时保持 onBeforeAction 代码到位时,我得到了一个例外.

可以在此处找到对异常的见解:SO 异常问题

异常的解决方法

上述 SO 问题中答案的主要要点是 您在 Route.onBeforeAction 中使用 Meteor.user() 但它无法访问此信息",以及何时,您的浏览器发出 GET/POST 请求" [服务器端路由?],到服务器它没有关于用户身份验证状态的任何信息."

根据同一个 SO 回答者的说法,解决方案是 找到一种替代方法来验证用户身份", 一种方法是使用 cookies"代码>.

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

** 所以,总而言之,为了允许服务器端路由,建议我使用 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() {//使用get_cookies函数解析cookies来自:https://stackoverflow.com/questions/3393854/get-and-set-a-single-cookie-with-node-js-http-servervar 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 loggingInUser = (user)?user.username : "未登录";var filePath = process.env.PWD + "/server/.files/users/test.pdf";控制台日志(文件路径);var fs = Npm.require('fs');var data = fs.readFileSync(filePath);this.response.write(data);this.response.end();}, {where: 'server'});

但这并没有像预期的那样工作,setCookie 代码由于某种原因无效.

我的问题

<块引用>

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

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

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

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

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

<块引用>

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

解决方案

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

if (Meteor.isClient) {Router.onBeforeAction(function () {if (!Meteor.user() || Meteor.loggingIn())this.redirect('welcome.view');别的this.next();},{除了:'welcome.view'});Router.onBeforeAction(function () {如果(流星.用户())this.redirect('home.view');别的this.next();},{仅:'welcome.view'});}Router.route('/pdf-server', function() {...}, {where: 'server'});

Forward

It seems that in Meteor, we cannot call a server side route to render a file to the page without some sort of work-around from our normal workflow, from what I've read about server side routes. I hope I'm wrong about this, and there's a simple way to achieve what I'm looking to do...

** Sorry if this is a little long, but I think in this case providing more background and context is warranted **

Software/Versions

I'm using the latest Iron Router 1.* and Meteor 1.* and to begin, I'm just using accounts-password.

Background/Context

I have an onBeforeAction that simply redirects the user to either the welcome page or home page base upon if the user is logged in or not:

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

In the same file, both/routes.js, I have a simple server side route that renders a pdf to the screen, and if I remove the onBeforeAction code, the route works (the pdf renders to the page):

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

Exception thrown on Server Route

It's beside the point, but I get an exception when I add the above server side route to the file and take the route /pdf-server, while keeping the onBeforeAction code in place.

Insights into the exception can be found here: SO Question on Exception

Solution to the Exception

The main gist of the answer in the SO Question above is "You use Meteor.user() in your Route.onBeforeAction but it has no access to this information", and when, "your browser make a GET/POST request" [Server side route?], "to the server it doesn't have any information regarding the user's authentication state."

The solution, according to the same SO answerer is to "find an alternative way to authenticate the user," and one way to do this is to use "cookies'".

So, following up on this, I found another SO answer (by the same answerer as before), where a method to set and get the cookies is outlined here: SO Cookies technique

** So, to summarize, in order to allow for server side routes, it is suggested I use cookies instead of something like Meteor.userId() or this.userId. **

Cookie related code added

So I added the following code to my project: 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);
    }
}); 

In my server side route, I changed the route to this:

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

But this does not work as expected, the setCookie code is not valid for some reason.

My Questions

Question 1: Setting/getting the cookies in the manner depicted in the SO Cookies technique doesn't seem to work for me, does this technique still work in '15?

Question 2: Using cookies, how do I inform the server of the authentication state based on these cookies? Or, another way, How does adding the cookie check in my server side route "inform" the server about the user? I could check for anything in this route really; I could reject any user, but somehow the server needs to "know" about the user logged in right?

Question 3: Is cookies the best way to go about this, or is there a simpler way to achieve the same thing?

Side Question: I've seen a few places where middle ware is used for server side routes, for example:

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

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

But none of these examples had security inside, will using middle ware in this way allow me to get around my problem?

解决方案

Your server-side routes are running the global onBeforeAction code (it's defined in a shared directory), which breaks because the server routes are simple REST endpoints which don't understand user authentication information (i.e. Meteor.user() doesn't work). The solution is to wrap the client-specific onBeforeAction calls with Meteor.isClient or simply move that code under the client directory. For example:

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

这篇关于Iron Router 和 Meteor 中的服务器端路由的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆