PHP(CLI)のプログラムをコマンドラインで実行し、画面からパスワードを入力させたいと考えています。


$stdin = fopen("php://stdin", "r");
$line = fgets($stdin, 64);

のようにすると、入力されたパスワードが画面に表示されてしまいます。

パスワードを画面に表示させずに入力させる良い方法をご存知でしたら教えてください。

回答の条件
  • 1人2回まで
  • 登録:2008/03/18 14:52:05
  • 終了:2008/03/21 18:37:26

回答(1件)

id:tobeoscontinue No.1

tobeoscontinue回答回数213ベストアンサー獲得回数522008/03/19 14:59:58

ポイント70pt

ANSI エスケープシーケンスに非表示(\033[8m)というのがあるのでこれで括ってやるのが一番簡単そうです。

function getpass($prompt) {
  $passwd = '';
  echo $prompt."\033[8m";
  $passwd = fgets(STDIN);
  echo "\033[0m";
  return $passwd;
}

echo getpass("Password:");

http://www.php.net/manual/ja/features.commandline.php#78672

を参考に書いてみました。

一文字読み込むのにbashのreadを使っているのでかなり効率悪いです。

function getKey() {
  // *を入力した場合、$valsではechoで*を展開するので入力されない。
  // ので"$valu"とする必要がある
  $ch = `read -s -n1 valu;echo -n "\$valu"`;
  if ($ch == chr(0x1b)) { // エスケープ文字列なら残りの文字も取り込む
    $ch .= `read -s -n1 valu;echo -n \$valu`; 
    $ch2 = `read -s -n1 valu;echo -n \$valu`;
    $ch .= $ch2;
    if (is_numeric($ch2))
      $ch .= `read -s -n1 valu;echo -n \$valu`; 
  }
  return $ch;
}

function getpass($prompt) {
  $passwd = '';
  echo $prompt;
  while (($ch = getKey()) != "") {
    if ($ch == chr(0x7f)) {
      if ($passwd) {
        $passwd = substr($passwd, 0, -1);
        echo "\033[1D \033[1D";
    } } else if (strlen($ch) == 1) {
      echo '*';
      $passwd .= $ch;
    }
  }
  return $passwd;
}

echo getpass("Password:");

表面的には機能を満足しているように見えますが、端末にはくわしくないのでセキュリティホールがあるかもしれません。

ダイレクト IO (DIO) 関数Ncurses 端末画面制御関数あたりが近いとは思いますがうまく出来ませんでしたorz。

id:yoski

おお、こんなエスケープシーケンスが。

大変助かります。試してみます。

ありがとうございました。

2008/03/21 18:36:59

コメントはまだありません

この質問への反応(ブックマークコメント)

トラックバック

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

絞り込み :
はてなココの「ともだち」を表示します。
回答リクエストを送信したユーザーはいません