一尘不染

流星中服务器端路由的身份验证

node.js

为服务器端路由验证用户的最佳方法(最安全,最简单)是什么?

软件/版本

我使用的是最新的Iron Router 1. 和Meteor 1. ,首先,我使用的是Accounts-password。

参考代码

我有一个简单的服务器端路由,可将pdf呈现到屏幕上:

两者/routes.js

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

举例来说,我想做些类似于该SO答案建议的操作:

在服务器上:

var Secrets = new Meteor.Collection("secrets");

Meteor.methods({
  getSecretKey: function () {
    if (!this.userId)
      // check if the user has privileges
      throw Meteor.Error(403);
    return Secrets.insert({_id: Random.id(), user: this.userId});
  },
});

然后在客户端代码中:

testController.events({
  'click button[name=get-pdf]': function () {
      Meteor.call("getSecretKey", function (error, response) {
        if (error) throw error;

        if (response) 
          Router.go('/pdf-server');
      });
  }
});

但是,即使我以某种方式使这种方法起作用,我仍然容易受到用户的攻击,只是他们输入了“ / pdf-
server”之类的URL,除非路由本身以某种方式检查了Secrets集合正确吗?

在Route中,我可以获取请求,并以某种方式获取标头信息?

Router.route('/pdf-server', function() {
  var req = this.request;
  var res = this.response;
}, {where: 'server'});

然后从客户端通过HTTP标头传递令牌,然后在路由中检查令牌是否来自Collection?


阅读 219

收藏
2020-07-07

共1个答案

一尘不染

除了使用url令牌作为其他答案之外,您还可以使用Cookie:

添加一些允许您设置cookie并在服务器端读取它们的软件包:

meteor add mrt:cookies thepumpinglemma:cookies

然后,您便可以将Cookie与您的登录状态同步起来

客户端

Tracker.autorun(function() {
     //Update the cookie whenever they log in or out
     Cookie.set("meteor_user_id", Meteor.userId());
     Cookie.set("meteor_token", localStorage.getItem("Meteor.loginToken"));
});

服务器端

在服务器端,您只需要检查此cookie是否有效(使用Iron路由器)

Router.route('/somepath/:fileid', function() {

   //Check the values in the cookies
   var cookies = new Cookies( this.request ),
       userId = cookies.get("meteor_user_id") || "",
       token = cookies.get("meteor_token") || "";

   //Check a valid user with this token exists
   var user = Meteor.users.findOne({
       _id: userId,
       'services.resume.loginTokens.hashedToken' : Accounts._hashLoginToken(token)
   });

   //If they're not logged in tell them
   if(!user) return this.response.end("Not allowed");

   //Theyre logged in!
   this.response.end("You're logged in!");

}, {where:'server'});
2020-07-07