preg_replace 删除该行的其余部分

preg_replace deletes rest of the line

我遇到了一个我不明白的 preg_replace() 问题:

我正在尝试从应用级日志、密码、令牌和其他敏感数据中删除。为此,我使用了这个:

$content = preg_replace(
        '/(?=\\"password\\")(.*)(?=\\")(.*)/i', '\"password\": \"[OBFUSCATED]\",',
        $content
    );

它与这个字符串完美配合:

"{\n \"username\": \"myuser@gmail.com\",\n
\"password\": \"1234密码\",\n \"role\": \"ROLE_USER\",\n
}"

正则表达式构建器就像这样: http://www.phpliveregex.com/

但是当我在我的应用程序中使用它时,它只是输出给我:

"{\n  \"username\": \"myuser@gmail.com\",\n  \"password\": \"[OBFUSCATED]\",

而不是预期的:

"{\n  \"username\": \"myuser@gmail.com\",\n  \"password\": \"[OBFUSCATED]\", \"role\": \"ROLE_USER\",\n }"

它删除了替换部分之后的其余行。我不明白为什么,我对正则表达式很糟糕...... 我怎样才能保留该行的其余部分以及为什么它在正则表达式构建器上工作而不在我的应用程序中工作(PHP v7.0.15)?

编辑:正如我在@Splash58 评论中看到的赞成票: 我不能使用数组,因为我无法提前看到需要混淆的值在哪里。它可以是 $json['object1']['object2']['password'] 或 $json['objectX'][0]['password']。我不想在我的数组中搜索要在潜在拥抱数组中删除的键,性能太差了。是不是更清楚了?

感谢任何提示! 波尔

不建议在此类字符串上使用正则表达式,但您的正则表达式存在一些明显的问题:

  • 它执行贪婪 . 匹配,因此您可能会匹配不属于一起的引号对。它还解释了您提到的问题——字符串的其余部分已被删除。
  • (?= ) 以错误的方式使用:代表前瞻 实际上并没有抓取 那些字符,而在您的用例中就可以了实际抓住它们(性能更好)
  • 为避免其他不匹配,最好还:
    • 检查是否存在冒号和白色 space,因为密码 属性.
    • 的 key/value 对之间不应出现任何其他内容
    • 检查字符串文字是否只有非引号的反斜杠转义,否则它表示字符串文字的结尾。

这里是修改后的表达式:

$content = preg_replace(
        '/(\\"password\\"\s*:\s*\\")((\\[^"]|[^\\])*)/i',
        '[OBFUSCATED]',
        $content
    );

请注意,您的输入字符串不是 JSON,因为 true JSON 不允许在您拥有反斜杠的地方出现文字反斜杠。例如,它不能有文字 \n,其中只允许白色 space。似乎您转义了某些字符(换行符、引号),在 JSON 中它们不应该那样转义。

要解决根本问题,您应该永远不要让敏感数据像那样在您的应用程序中四处浮动。

至少 你应该只传递一个密码哈希(即由 password_hash 生成的)周围,​​但即使这样也只是为了实际验证用户。不要将那些东西保留在内存中超过需要!

一旦您解决了根本问题,即在不需要的地方拥有不安全的敏感数据,您会发现您不再需要 "clean up" 您的应用程序日志 :)