【问题标题】:How to pass a bash variable to a php function without an undefined variable error message?如何在没有未定义变量错误消息的情况下将 bash 变量传递给 php 函数?
【发布时间】:2017-05-25 16:28:59
【问题描述】:

我正在生成一个密码哈希,我想根据用户输入在脚本中稍后使用它。我尝试了以下 bash 变量的语法变化:

#!/bin/bash

printf "Enter password:"
read pw

php -r 'echo password_hash("$pw", PASSWORD_DEFAULT, [ "cost" => 11 ]) . "\n";'

我得到了正确的哈希值,但只有在我得到一个未定义的变量警告之后。

当我将变量放在单引号 '$pw' 中,然后将密码输入为“password”或“password”时,我没有收到错误。

如何在没有未定义变量错误消息的情况下将 bash 变量传递给 php 命令或以其他方式将其分配给 bash 脚本中的 php 变量?

【问题讨论】:

    标签: php bash shell


    【解决方案1】:

    通过环境传递变量是可行的方法(因为密码永远不会被更多的进程或用户访问,而不是通过 php 的命令行传递)。

    这应该使用 export 内置函数来完成,以符合 POSIX。或者,也可以使用仅限 Bash 的 declare -x

    printf "Enter password:"
    read pw
    
    # export pw to the environment:
    export pw
    
    # the process executing your php program reads pw from the
    # environment that it inherited from its parent process:
    php -r 'echo password_hash($_SERVER["pw"], PASSWORD_DEFAULT, [ "cost" => 11 ]) . "\n";'
    

    请注意,超全局数组的填充取决于您的 PHP 配置中 variables_order 的值(S 字符必须在此设置的值中才能填充 $_SERVER)。

    【讨论】:

      【解决方案2】:
      php -r 'echo password_hash("$pw", PASSWORD_DEFAULT, [ "cost" => 11 ]) . "\n";'
      

      Bash 中的单引号字符串不会进行变量扩展,因此您实际上是将字符串 $pw 传递给 PHP 进行解析,并且由于它不存在,您会收到来自 PHP 的警告。你得到的哈希可能是空字符串,不是你想要的字符串。尝试在脚本中将php -r 替换为echo,以查看传递给php 的确切内容。

      出于安全原因,对export 变量的建议是一个不错的选择(尽管您应该使用$_ENV,而不是$_SERVER),但是在一般情况下(即不是密码),这不是必需的。一旦你理解了Bash's quoting semantics(这可能会让人困惑),正确引用字符串以便在 Bash 中评估变量就很容易了。

      对于这种情况,只需反转字符串中的单引号和双引号就足够了:

      php -r "echo password_hash('$pw', PASSWORD_DEFAULT, [ 'cost' => 11 ]) . '\n';"
      

      【讨论】:

      • 这更符合我一直在寻找/困惑的内容。谢谢你的解释。不过,我也很欣赏 Michael Jaros 的回答!
      • @DonPeat: $_ENV 在许多环境中默认不填充(这取决于variables_order 的值)。并且通过字符串替换传递密码使其可以通过命令行对该计算机上的其他用户可见,而通过环境传递密码时则不是这种情况,因此在某些环境中这可能是一个安全问题。
      • @MichaelJaros 这是一个内部运行的脚本,因此不必担心它本身,但肯定很高兴知道。那么一般来说,导出到环境是更好的做法吗?
      • @DonPeat:命令行上的秘密可能是个问题(例如/proc/cmdline,shell 历史记录)。通过环境传递秘密更好,但这是一个真正的问题,尤其是在较旧的 Unix 上,并且仍然应该被认为具有潜在危险,因为至少所有子进程都可以访问秘密。在启动孩子后重置变量不会解决这个问题,因为拥有秘密的孩子也可以有孩子。秘密应该存储在通过权限保护的文件中,或者通过进程之间的 IPC(管道、套接字等)传递。
      • @MichaelJaros 专门用于密码,我同意你的看法,尽管问题背后的问题只是在 Bash 中引用错误。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-19
      • 1970-01-01
      • 2013-04-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多