Bash: 隱藏用戶輸入/密碼
Bash: 隱藏用戶輸入/密碼
有時,我們或者需要隱藏用戶輸入,令用戶的需入不會在終端機(terminal)中顯示,特別是當我們的 script 需要取得用戶密碼時。
tl;dr
1. read -s
我們可以使用 read
指今加上 -s
選項來讀取密碼,這樣我們的 script 就不會顯示出用戶輸入的密碼。
例如:
#!/bin/bash
read -s -p "Enter password: " password
echo
echo "password: $password"
範例輸出:
noob@learnfromnoobs:~$ ./input_password_read.sh
Enter password:
password: 123456
如想知道更多,請參閱 read --help
。
2. stty
我們可以使用 stty -echo
和 stty echo
包著我們用作取得用戶密碼的指令,這樣會關掉這些指令的 echo, 令這些指令不會有任何輸出。
例如:
#!/bin/bash
stty -echo
echo -n "Enter password: "
read password
echo
echo "password: $password"
stty echo
範例輸出:
noob@learnfromnoobs:~$ ./input_password_stty.sh
Enter password:
password: 123456
注意當我們輸入密碼時,我們是無法看到我們正在輸入甚麼的,上述兩個方法都會有同樣的結果。 就是這樣了!當然,千萬不要像菜鳥一樣使用 “123456” 作為密碼呀!
ts;wm
stty 是甚麼?
根據 stty 的 man page,stty 是一個用作改變並列印終端機(terminal)設置的工具。
如果我們不帶參數執行這指令,則會輸出波特率(baud rate),行的約束規則(line discipline number),以及與 stty sane
不同的設置。
noob@learnfromnoobs:~$ stty
speed 38400 baud; line = 0;
-brkint ixoff -imaxbel iutf8
我們可以試下把 echo 關掉,然後再次執行 stty
,由於我們已經把 stty
關掉,所以當我們輸入 stty
時看不到自己打字是正常的,我們可以從 stty
最後一行的輸出中看到 “-echo”,表示 echo 已經被關掉。
noob@learnfromnoobs:~$ stty -echo
noob@learnfromnoobs:~$ speed 38400 baud; line = 0;
-brkint ixoff -imaxbel iutf8
-echo
我們更可以使用 stty -a
來查看 stty 現在所有的設置。
noob@learnfromnoobs:~$ stty -a
speed 38400 baud; rows 46; columns 104; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>; eol2 = <undef>; swtch = <undef>;
start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; discard = ^O; min = 1; time = 0;
-parenb -parodd -cmspar cs8 -hupcl -cstopb cread -clocal -crtscts
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon ixoff -iuclc -ixany -imaxbel
iutf8
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl echoke -flusho
-extproc
如想知道更多,請參閱 man stty
或者 info stty
。
用星號顯示密碼
注意這個方法會暴露你的密碼長度,直接不顯示用戶的輸入會是個更好的方法,不過如果你真的想使用這個方法,你可以參考以下方式。
1. systemd-ask-password
如適用
如果你可以使用 systemd-ask-password
這個工具,你可以直接使用它來取得用戶密碼。
注意這工具有一個預設的 60 秒逾時,我們可以使用選項 --timeout=0
把逾時功能關掉。
#!/bin/bash
password=`systemd-ask-password "Enter password:"`
echo "password: $password"
範例輸出:
noob@learnfromnoobs:~$ ./input_password_systemd.sh
Enter password: ******
password: 123456
2. 自己寫吧
如果你不喜歡 systemd-ask-password
的方法(又或者你想用星號以外的其他符號),你可以寫一個自己的程式,這也是一個有趣的練習。
我們的程式應該要允許用戶修改輸入,因此我們的程式需要有處理 backspace 和 EOL 的能力,我們要小心用戶不能刪掉輸入提示(prompt)。
#!/bin/bash
unset password
unset chartCount
echo -n "Enter password: "
while IFS= read -r -n1 -s char; do
case "$char" in
$'\0')
break
;;
$'\177')
if [ ${#password} -gt 0 ]; then
echo -ne "\b \b"
password=${password::-1}
fi
;;
*)
chartCount=$((chartCount+1))
echo -n '*'
password+="$char"
;;
esac
done
echo
echo "password: $password"
範例輸出:
noob@learnfromnoobs:~$ ./input_password_asterisk.sh
Enter password: ******
password: 123456
以上程式的小解釋:
- 我們在 while loop 中使用了
IFS=
,否則如果用戶的密碼有空白符號,while loop 就會被中斷,如想知道更多,請參閱man bash
,搜尋 “IFS”。 - 我們在
read
指令中使用了選項-r
,這允許用戶使用含有 ’\’ 的密碼。 echo -ne "\b \b"
是用作刪除密碼最後的一個字元,\b
把指標(cursor)向左移一格,然後我們輸出一個空白字元,最後再次用\b
向左移一格,這就是刪除一個字元背後的完整動作;而選項-e
則是用來使 echo 能解釋 ’\’ 的轉義功能。
總結
總結,我們一共提供了 4 個隱藏用戶輸入或者密碼的方法:
- 使用
read -s
- 使用
stty -echo
- 使用
systemd-ask-password
- 按自己需要寫適合自己的程式
無論你最後採用了哪個方法,我都希望你享受閱讀這篇文章。
記得要不斷學習,have fun!