隐藏从Meteor Methods调用的秘密服务器代码

时间:2017-01-30 19:11:33

标签: javascript meteor require

我正试图围绕如何在Meteor方法中隐藏客户端的秘密服务器代码The docs seem to imply以下是如何完成的一般模式。 https://guide.meteor.com/structure.html#using-require

(请注意,根据文档,我使用的是require而不是导入,因为import无法在条件块中使用。)

首先,这是一个名为methods.js的文件中定义的方法,并在客户端和服务器上导入:

/* methods.js */

let ServerCode
if (Meteor.isServer) {
  ServerCode = require('/imports/server-code.js')
}

Meteor.Methods({
  'myMethodName': function() {
    // ... common code
    if (Meteor.isServer) {
      ServerCode.secretFunction()
    }
    // ... common code
  }
})

其次,这是/imports/server-code.js中的秘密服务器代码,我试图不发送给客户端:

/* server-code.js */

class ServerCode {
  secretFunction() {
    console.log('TOP SECRET!!!!')
  }
}

const ServerCodeSingleton = new ServerCode()
module.exports = ServerCodeSingleton

当我检查发送到客户端浏览器的源时,我仍然看到我的秘密服务器代码被发送到客户端:

Screenshot of the server code being sent to the client

即使我进行了制作,我仍然可以搜索并找到“TOP SECRET !!”串。我觉得我对require的工作方式的理解太天真了,但Meteor的文档使它看起来如此简单。那么隐藏从Meteor Methods调用的密码的正确方法是什么?

2 个答案:

答案 0 :(得分:1)

我终于想到了这一点。

简短的版本是,忽略它在这里所说的;我认为这是不正确的或至少是误导性的:

https://guide.meteor.com/structure.html#using-require

请按照此处的说法进行操作:

https://guide.meteor.com/security.html#secret-code

更长的解释是:在仅服务器文件中,import密码并将其分配给全局变量。然后,在< em> common file ,使用isServer(或!isSimulation)有条件地引用该全局变量。

所以我原来的例子可能会像这样重写:

/*   /imports/methods.js   */

// Note: no conditional use of require this time

Meteor.Methods({
  'myMethodName': function() {
    // ... common code
    if (Meteor.isServer) {
      ServerCode.secret() // <-- Defined as a global outside of this file!
    }
    // ... common code
  }
})

因此密码文件可能如下所示:

/*   /imports/server-code.js   */

class _ServerCode {
  secret() {
    console.log("Shhhhhh, I'm secret()!")
  }
}
// Here's the global variable:
SecretCode = new _SecretCode()

然后在仅限服务器文件中,它可能如下所示:

/*   /server/server-main.js   */

import '/imports/secret-code' // <-- declare the global
import '/imports/methods' // <-- use the global in here

然后在仅限客户端文件中,它可能如下所示:

/*   /client/client-main.js   */ 

import '/imports/methods'

//...

Meteor.call('myMethodName')

现在,客户端和服务器都可以在方法体(DRY)中执行与 部分 完全相同的代码,而某些密码可以是仅服务器并赢得也不会被送到客户端。不得不求助于使用全局变量,这有点烦人,但也许这是最干净的选择,直到import的更高版本出现,支持内置的模块延迟加载。

答案 1 :(得分:0)

编辑:无视答案,没有解决OP对DRY代码或乐观更新的渴望。

默认情况下,Meteor实现了关于文件的急切加载方案。你的methods.js就是一个例子。

如果文件位于名为“client”的文件夹下的任何目录中,则该文件仅提供给客户端。同样,“服务器”下的任何文件仅提供给该文件夹。这就是你如何处理确保文件只服务于服务器。

正如您所发现的那样,“Meteor.isServer”构造仅限制在环境中运行的内容,而不是在那里提供的内容。

我通常会实现像这样的Meteor方法:

服务器/一些/路径/ stuff.js:

// this is only on the server
Meteor.methods({
    'getStuff': function() {
        return "stuff";
    }
});

的客户机/一些/路径/ clientStuff.js:

// this is only on the client, calling the server method
Meteor.call('stuff', function(error, result) {
    if (error && error.reason) {
        alert(error.reason);
    }
    else {
        // use result
    }
});

关于要求,你为什么要使用它?

我看到你在/ imports中有代码,Meteor将其视为特殊代码并且不会急于加载。这告诉我你明确地导入了这些东西。

MDG对目录结构,ES15模块以及如何加载代码有一些强烈的建议,他们在这里详细说明:

https://guide.meteor.com/structure.html

你会注意到他们没有使用require,并且指定的模块与你的模式不同。