【问题标题】:How do you prevent a NodeJS server from potentially exposing function code?如何防止 NodeJS 服务器潜在地暴露函数代码?
【发布时间】:2019-04-28 05:50:59
【问题描述】:

假设您正在构建一个银行应用程序后端。您想使用返回余额的字符串响应用户,但忘记添加()

class User {
  constructor() {console.log("ctor")}
  balance() { console.log("secret balance code")}
}

那么在引用用户时,不要这样写:

const userA = new User();
return `Your balance is $${userA.balance()}`;

我不小心写了这个:

const userA = new User();
return `Your balance is $${userA.balance}`;

可悲的是输出:

'Your balance is balance() { console.log("secret balance code")}'

这会泄露源代码。

【问题讨论】:

  • 编写测试覆盖率 - 您可以确保响应符合您的预期。
  • ...或者使用 TypeScript :) 它涵盖了大多数情况

标签: javascript


【解决方案1】:

一种解决方法是像这样覆盖所有函数的toString

> Function.prototype.toString = () => {return "bla"}
[Function]
> '' + new User().balance
'bla'

【讨论】:

  • 重写不属于你的原型是一个非常糟糕的主意。覆盖Function 肯定会破坏一些调试和日志工具。
  • 这是另一种方式,但您必须单独保护每个功能,因此不会被接受。 stackoverflow.com/questions/12799996/… 我认为 typescript lint 警告是解决这个问题的最佳选择。
【解决方案2】:

您不必担心,如果您忘记了某些东西,那么测试将有助于找到它。当他有一个严肃的项目时,没有人会在没有测试的情况下部署到生产环境中。编写测试比尝试纠正语言行为要好。

【讨论】:

    【解决方案3】:

    在响应请求时,您无疑将通过某种序列化程序运行响应。 JSON、CBOR 等。在该层处理。

    幸运的是,如果您要返回 JSON 数据,它已经被处理了:

    JSON.stringify(someFunction);
    // undefined
    

    如果你真的要返回纯文本字符串,你仍然可以有这样一个层来确保你不会输出函数。

    【讨论】:

      【解决方案4】:

      我有一个肯定比原始模板慢的解决方案,但它就是这样。

      所以基本上我只是发送一个包含我想要解析的所有字符串的上下文对象。在实际的字符串替换之前,我只检查参数的类型。

      function resolveTemplates(str, args){
        if(args && Array.isArray(args) && args.length){
          args.forEach((argument) => {
            // check here for any unwanted types
            if(typeof arg === 'function'){
              throw new Error('Cannot send function to create raw Strings')
            }
          })
        }
      
        const rx = /\{([^{}]*)\}/g;
      
        let match = {};
        let matches = [];
        while(match = rx.exec(str)){
          matches.push(match)    
        }
      
        matches.reverse();
        matches.forEach(function(match){
          const key = match[1];
          const index = match.index;
          str = str.slice(0, index) + args[key] + str.slice(index + 2 + key.length) 
        })
      
        return str;
      }
      
      
      resolveTemplates('Hello! My name is {firstName} {lastName}', {firstName: 'Shobhit', lastName: 'Chittora'})
      

      PS:您可以调用函数,而不是将函数作为参数抛出错误。但是将函数绑定到正确的上下文可能需要考虑并且通常不建议这样做。

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-02
      • 1970-01-01
      • 2023-01-26
      • 1970-01-01
      • 1970-01-01
      • 2019-05-09
      相关资源
      最近更新 更多