【PHP】CLIでの標準入力マスキング

PHP

パスワードや暗証番号などの機密情報をターミナルの標準入力でタイプする際に、画面上では見えないように別の文字でマスキングする方法のメモです。(制作協力:ChatGPT-4o)

動作環境

  • PHP 8.4.7 / 8.3.21 / 8.2.28 / 8.1.32 / 8.0.30 / 7.4.33
  • Ubuntu24.04.2 LTS (WSL2 / Windows11)
  • VSCode Terminal (VSCode 1.100.0)

stty を使用するため、Windowsは対象外です。

仕様概要

  • maskInput() 関数で呼出、入力値を返す
  • 入力された文字列は表示しない
  • キー入力毎にマスキング文字列「●」を表示
  • バックスペース1回で1文字削除、「●」表示も連動
  • [Enter]押下で入力終了、入力値を返す
  • [Ctrl] + [C] で強制終了

maskInput() 関数

次のようなユーザー定義関数で上記仕様の実装ができます。

<?php

function maskInput(string $label): string
{
    $maskChar = "●";

    echo $label . ": ";

    // 現在の端末設定を保存
    $originalStty = rtrim(shell_exec("stty -g"));

    // 非表示・raw入力モードに設定
    shell_exec("stty -echo");
    shell_exec("stty raw");

    $value = "";
    try {
        // 標準入力制御
        while (true) {
            $char = fgetc(STDIN);
            // Ctrl+C (ASCII 3)
            if ($char === "\x03") {
                echo "\r\n^C\r\n";
                // 復元して終了
                shell_exec("stty $originalStty");
                exit(130);
            }
            // 改行コードで入力モード終了
            if ($char === "\n" || $char === "\r") {
                break;
            } elseif (ord($char) === 127 || ord($char) === 8) { // Backspaceハンドリング
                if (strlen($value) > 0) {
                    $value = substr($value, 0, -1);
                    echo "\033[1D \033[1D"; // Move back, erase, move back again
                }
            } else {
                $value .= $char;
                echo $maskChar;
            }
        }
    } finally {
        // 端末設定を元に戻す
        shell_exec("stty '$originalStty'");
        echo PHP_EOL;
    }

    return $value;
}

$password = maskInput("パスワードを入力してください。");
$secret = maskInput("暗証番号を入力してください。");

var_dump($password, $secret);

動作確認

上記のコードを実行すると下図のようになります。

キーを1回押す毎にマスキング文字「●」が文字数に応じて表示されます。

バックスペースを押すと、「●」が1個減ります。

[Enter]押下時に入力終了となり、入力した文字列を返します。

[Ctrl] + [C] で強制終了できます。

コメント

タイトルとURLをコピーしました