我正在尝试找到一种解决方案,可以通过
read
命令按字符过滤用户输入的密码(不是通过 read -e
,这会阻止直接响应击键),实时过滤和处理特殊字符。作为第一个字符,不应允许使用 space
或任何 special chars
。如何实现这一点,同时避免不可打印的ESC-sequences
(除了backspace
之外的所有移动光标的内容),这可能会污染密码输入?
# Set of allowed chars
allowedDefaultChars='[a-zA-Z0-9]'
allowedSpecialChars='[-_ \(\)/~?!§,.\#+]'
pw=
while true; do
read -rsn 1
if [[ $REPLY ]]; then
...
pw+="$REPLY"
fi
done
echo "$pw"
通过进一步的调查和实验,我得出以下解决方案:
#! /bin/bash
# Validated password entry with filtered ESC sequences / disabled ESC and a set of allowed special chars / disallows special chars or space as 1st char
validate_password() {
local pw
local escKey=$'\x1B'
local backspaceKey=$'\x7f'
local allowedDefaultChars='[a-zA-Z0-9]'
local allowedSpecialChars='[-_ \(\)/~?!§,.\#+]'
echo -e "\n*** Password validation ***\nAllowed special charset, unless 1st char is >> $allowedSpecialChars <<\n\nEnter password:" >/dev/tty
local isFirstChar="1"
while true; do
read -rsn 1
# Stop on ENTER
if [[ ${#REPLY} -eq 0 ]]; then
break
fi
# Filter ESC sequences / block ESC key
if [[ $REPLY == $escKey ]]; then
while true; do
read -rsn1 -t 0.001
if [[ ${#REPLY} -eq 0 ]]; then
break
fi
done
continue
fi
# Block 1st char special char or space
if [[ $isFirstChar ]]; then
if [[ $REPLY != $allowedDefaultChars ]]; then
echo -e "First char must not be a special char or space!\e[1A" >/dev/tty
continue
fi
# Clear and stay in message line
echo -e "\e[K\e[1A" >/dev/tty
unset -v isFirstChar
fi
# Filter out disallowed chars for input
if [[ $REPLY == $allowedDefaultChars || $REPLY == $allowedSpecialChars ]]; then
pw+="$REPLY"
printf '%s' '*' >/dev/tty
# Backspace - delete last entered password char and a '*' from dispay
elif [[ $REPLY == $backspaceKey ]]; then
pw="${pw:0:-1}"
printf '%s' $'\e[1D\e[0K' >/dev/tty
fi
done
echo "$pw"
unset pw
echo -e >/dev/tty
}
echo -e "PW IS: $(validate_password)"
该函数阻止任何特殊字符或空格作为第一个字符的输入,并显示警告消息。输入第一个有效字符后,来自有效组
allowedDefaultChars
或 allowedSpecialChars
的所有其他字符都会添加到本地 pw
变量中,并在屏幕上打印下一个 *
。
如果将函数调用捕获到 var 中,所有可视输出都会重定向到
>/dev/tty
,以免污染密码。
如果按下退格键,则先前存储的下一个字符及其在屏幕上的
*
表示形式将再次被删除。
所有直接从键盘可访问的键生成
ESC-sequences
/不可打印字符,都应成功抑制和过滤(ESC、F1-F12、箭头键、home、end、pgup、pgdn,...),即使在过多的情况下,快速多次按键,不会“泄露”按键序列。
ENTER
输入完成。
我还测试了来自
KeepassXC
的复制粘贴输入,这似乎工作正常(除非粘贴的密码包含禁用字符)。