如何按字符过滤密码用户输入的特殊字符,抑制 Bash 中的 ESC 序列?

问题描述 投票:0回答:1

我正在尝试找到一种解决方案,可以通过

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"
bash user-input special-characters real-time ansi-escape
1个回答
0
投票

通过进一步的调查和实验,我得出以下解决方案:

#! /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
的复制粘贴输入,这似乎工作正常(除非粘贴的密码包含禁用字符)。

© www.soinside.com 2019 - 2024. All rights reserved.