Shellアナログパスワード入力

4730 ワード

前にネット上でshellシミュレーションパスワード入力機能を使用するという投稿を見ました.通常sudoコマンドを使用すると、パスワードを入力するプロンプトが表示され、shellはキーボード入力をすべて遮断します(「*」は表示されず、何も表示されません★_★).その後、いろいろな資料を調べて、比較的簡単な実現方法を2つ見つけました.
1、read -s
readは、ユーザの入力を読み出し、指定した変数に格納する.-sオプションを指定すると、入力は表示されません.実装コードは次のとおりです.
#!/bin/bash
 
echo -n "Username: "
read username
 
echo -n "Password: "
read -s password
 
echo -e "
" echo "Username is $username" echo "PassWord is $password"
簡単な分析では、echoの-nオプションは、デフォルトでは出力されないリターン改行文字を指定します(echoはデフォルトで情報を出力すると自動的にリターン改行します).-eオプションは、echoが出力情報のエスケープ文字を認識できるようにします.readは、ユーザ入力usernameおよびpasswordをそれぞれエコーと非エコーで格納する.
出力結果は次のとおりです.
Username: Linus
Password:
UserName is Linus
PassWord is I don't know
2、stty -echo
sttyは、端末の特性を印刷または変更するために使用されます.ここでは-echoオプションを使用します.manマニュアルを参照してください.入力文字をマスクするために使用されます(つまり、入力がエコーされません.ただし、ここでは-echoオプションは入力文字のエコーをマスクするだけで、他の出力に制限はありません.たとえばshellスクリプトには次の2つのコマンドがあります.
stty -echo
echo "Can you see me?"
2行目は、入力デバイスによって生成されないため、端末に出力されます.実装コードは次のとおりです.
#!/bin/bash
 
STTY_RESTORE=$(stty -g)
 
echo -n "Username: "
read username
 
stty -echo
echo -n "Password: "
read password
 
echo -e "
" echo "Username is $username" echo "Password is $password" stty $STTY_RESTORE
簡単に分析すると、sttyの-gオプションは現在の端末特性のパラメータを出力し、プログラムの開始時に端末特性を保存し、プログラムの実行後に元の端末特性(プログラムの最後の行)を復元するために使用されます.パスワードを入力する前にstty-echoコマンドを使用して入力エコーをマスクします.
出力結果は次のとおりです.
Username: Linus
Password:
Username is Linus
Password is Oh, I told you I don't know!
readはbash shellの埋め込みコマンドであり、sttyはそうではないことに注意してください.すなわち、別のshellに置き換えると、readコマンドがないか、readの-sオプションがない可能性があります.言い換えれば、sttyで実現されるプログラムは移植可能であり、readで実現されるプログラムは必ずしもそうではない.
これによりshellシミュレーションパスワード入力の基本機能を実現した.しかし、普段最も多く見られるのは、パスワードを入力するときに「*」や他の文字を返すことだと思います.同時に、これも人間的だと思います.そこで様々な資料を調べ続け、実現方法を見つけた.http://bbs.chinaunix.net/forum.php?mod=viewthread&tid=543875まずlijunlingが提供した実現構想に感謝します.しかし、このコードは私の机械(そうだ、自己绍介を忘れた.私はUbuntu 11.04を使っている.shellはGNU bash shell 4.2.8(1)-release(i 686-pc-linux-gnu))の运行异常で、リターンを识别できない.キーボードを速く打つ时、ある文字は明文で表示され、パスワードに记录されていない.そこでこのコードの大体の考え方に従って引き続き資料を調べて、最終的に私の機械の上で同じ機能を実現しました.また、キーボードのスナップショットの問題を解決し、チェックアウトキーの機能を追加するための最適化も行いました.
3、dd if=/dev/tty bs=1 count=1 2>/dev/null; stty -echo cbreak
ddは、入力内容を任意にフィルタリング、変換するなどの対応する操作を行った後、出力(デフォルトは標準入力から標準出力)にコピーするために使用され、ここでは入力された文字を得るために使用される.実装コードは次のとおりです.
#!/bin/bash
 
STTY_RESTORE=$(stty -g)
 
echo -n "Username: "
read username
 
echo -n "Password: "
stty -echo cbreak
while true
do
        character=$(dd if=/dev/tty bs=1 count=1 2> /dev/null)
        case $character in
        $(echo -e "
")) break ;; $(echo -e "\b")) if [ -n "$password" ]; then echo -n -e "\b \b" password=$(echo "$password" | sed 's/.$//g') fi ;; *) password=$password$character echo -n '*' ;; esac done stty $STTY_RESTORE #stty -cbreak echo echo -e "

Username is $username" echo "Password is $password"
簡単な分析では、今回sttyを使用してcbreakオプションを多く指定しました.manマニュアルを参照してください.erase、kill、wearse、rprntオプションのセットです.文字を入力すると、車に戻ってから一緒に報告するのではなく、すぐに報告する機能を実現します.次に、入力した文字を保存し、ブランチに入り、入力した文字に基づいて対応する操作を実行するデッドサイクルに入ります.
ddコマンドは、入力ファイルが/dev/tty、すなわち標準入力であることを示し、1バイトずつ読み書き(bs)、入力された1ブロックのみをコピーし(count)、出力ファイルが指定されていない、すなわち標準出力に出力する.ddコマンドは、実行中にいくつかのプロンプト情報を出力しますが、実際には出力したくないので、/dev/nullデバイスにリダイレクトする必要があります.では、この文を通ると、characterも入力した文字を得ます.
次にブランチに入り、リターンキーであればデッドサイクルを飛び出し、パスワード入力を終了します.チェックアウトキーの場合は、格納されているパスワード(password)が空でない場合は、カーソルを1つ前に移動させ、スペースを出力してから1つ前に移動(「bb」)すると、アスタリスク表示が削除されます.同時に、格納されたパスワードの最後の文字を削除します(sed's/.$//g'は、最後の文字に一致し、空の文字に置き換えられます).最後に、他の文字を入力した場合はpasswordに追加し、アスタリスクを出力します.
パスワード入力が完了したらsttyを使用して以前の端末特性を復元します.また、コメントのコマンドを使用して、リカバリ前のプロパティを明確に指定することもできます.
出力結果は次のとおりです.
Username: Linus
Password: **********************
Username is Linus
Password is Oh, my god! Help me!!!
 
実際のテスト中に発生した問題:
1、プログラムの18行目、$passwordに二重引用符を付けないと、その変数が空の文字列であるかどうかを判断できません.
2、プログラムの20行目、echo$password(二重引用符なし)と書くと、echoは変数の行頭と行末のスペースを自動的にフィルタします.例を挙げて、[スペース]a[スペース]b[スペース][退格]を入力すると、echoパイプがsedに与える値はa[スペース]bとなります.このとき4つのアスタリスク(5-1文字入力)があるがpasswordには2文字しか記憶されていない(a[スペース]、bは削除されている).
3、このプログラムはF 1~F 12、ESCなどの機能キーを認識できない.これらの機能キーは複数の文字で表されるが、stty cbreakは各文字がすぐに報告され、複数の星番号が表示されるからだ.