隐藏从 Meteor Methods 调用的秘密服务器代码
Hide secret server code called from Meteor Methods
我正在努力思考如何在 Meteor Methods 中对客户端隐藏秘密服务器代码。 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
但是 当我检查发送到客户端浏览器的源代码时,我仍然看到我的秘密服务器代码被发送到客户端:
即使在进行生产构建时,我仍然可以搜索并找到 'TOP SECRET!!' 字符串。我觉得我对 require
如何工作的理解太天真了,但是 Meteor 文档让它看起来很简单。那么隐藏从 Meteor Methods 调用的秘密代码的正确方法是什么?
编辑:无视答案,没有解决 OP 对 DRY 代码或乐观更新的需求。
默认情况下,Meteor 对文件实施 eager-loading 方案。你的 methods.js 就是一个例子。
如果文件位于名为 "client" 的文件夹下的任意目录中,则该文件仅提供给客户端。同样,"server" 下的任何文件仅提供给该文件夹。这就是您处理确保文件仅提供给服务器的方式。
如您所见,"Meteor.isServer" 构造仅限制环境中 运行 的内容,而不是那里提供的内容。
我通常像这样实现 Meteor 方法:
server/some/path/stuff.js:
// this is only on the server
Meteor.methods({
'getStuff': function() {
return "stuff";
}
});
client/some/path/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
}
});
关于 require,你为什么要用它?
我看到您在 /imports 中有代码,Meteor 将其视为特殊代码并且不会急切加载。这告诉我你明确地导入了这些东西。
MDG 对目录结构、ES15 模块以及如何加载代码有一些强烈的建议,他们在这里详细介绍:
https://guide.meteor.com/structure.html
您会注意到他们不使用 require,并且指定模块的方式与您的做法不同。
我想我终于想通了。
简短的版本是,忽略这里说的;我认为它不正确或至少具有误导性:
https://guide.meteor.com/structure.html#using-require
并按照此处的说明进行操作:
https://guide.meteor.com/security.html#secret-code
更长的解释是:在server-only文件中,import
密码并将其赋值给一个全局变量。 然后,在 公共文件 中,使用 isServer
(或 !isSimulation
)有条件地引用该全局变量。
所以我原来的例子可能是 re-written 这样的:
/* /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-only 文件中它可能如下所示:
/* /server/server-main.js */
import '/imports/secret-code' // <-- declare the global
import '/imports/methods' // <-- use the global in here
然后在 client-only 文件中它可能看起来像这样:
/* /client/client-main.js */
import '/imports/methods'
//...
Meteor.call('myMethodName')
现在客户端和服务器都可以在方法体中执行一些完全相同的代码(DRY),而一些秘密code 可以是 server-only 并且也不会发送给客户端。不得不求助于使用全局变量有点烦人,但也许这是最干净的选择,直到出现支持 built-in lazy-loading 模块的更漂亮的 import
版本。
我正在努力思考如何在 Meteor Methods 中对客户端隐藏秘密服务器代码。 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
但是 当我检查发送到客户端浏览器的源代码时,我仍然看到我的秘密服务器代码被发送到客户端:
即使在进行生产构建时,我仍然可以搜索并找到 'TOP SECRET!!' 字符串。我觉得我对 require
如何工作的理解太天真了,但是 Meteor 文档让它看起来很简单。那么隐藏从 Meteor Methods 调用的秘密代码的正确方法是什么?
编辑:无视答案,没有解决 OP 对 DRY 代码或乐观更新的需求。
默认情况下,Meteor 对文件实施 eager-loading 方案。你的 methods.js 就是一个例子。
如果文件位于名为 "client" 的文件夹下的任意目录中,则该文件仅提供给客户端。同样,"server" 下的任何文件仅提供给该文件夹。这就是您处理确保文件仅提供给服务器的方式。
如您所见,"Meteor.isServer" 构造仅限制环境中 运行 的内容,而不是那里提供的内容。
我通常像这样实现 Meteor 方法:
server/some/path/stuff.js:
// this is only on the server
Meteor.methods({
'getStuff': function() {
return "stuff";
}
});
client/some/path/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
}
});
关于 require,你为什么要用它?
我看到您在 /imports 中有代码,Meteor 将其视为特殊代码并且不会急切加载。这告诉我你明确地导入了这些东西。
MDG 对目录结构、ES15 模块以及如何加载代码有一些强烈的建议,他们在这里详细介绍:
https://guide.meteor.com/structure.html
您会注意到他们不使用 require,并且指定模块的方式与您的做法不同。
我想我终于想通了。
简短的版本是,忽略这里说的;我认为它不正确或至少具有误导性:
https://guide.meteor.com/structure.html#using-require
并按照此处的说明进行操作:
https://guide.meteor.com/security.html#secret-code
更长的解释是:在server-only文件中,import
密码并将其赋值给一个全局变量。 然后,在 公共文件 中,使用 isServer
(或 !isSimulation
)有条件地引用该全局变量。
所以我原来的例子可能是 re-written 这样的:
/* /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-only 文件中它可能如下所示:
/* /server/server-main.js */
import '/imports/secret-code' // <-- declare the global
import '/imports/methods' // <-- use the global in here
然后在 client-only 文件中它可能看起来像这样:
/* /client/client-main.js */
import '/imports/methods'
//...
Meteor.call('myMethodName')
现在客户端和服务器都可以在方法体中执行一些完全相同的代码(DRY),而一些秘密code 可以是 server-only 并且也不会发送给客户端。不得不求助于使用全局变量有点烦人,但也许这是最干净的选择,直到出现支持 built-in lazy-loading 模块的更漂亮的 import
版本。