【问题标题】:Bash: Masking user input for a password, with * support for backspace and special charactersBash:屏蔽用户输入的密码,*支持退格和特殊字符
【发布时间】:2020-12-25 22:17:00
【问题描述】:

我在下面有这个 sn-p 的想法是通过 @SiegeX@mklement0 屏蔽来自 this question 的密码输入。

太好了,我唯一想要的补充是只删除输入字符的长度,所以我们不会抹去整行。

这个我不是很懂,所以遇到了bug。

在下面输入“12345”并退格,数字不会“退格”;没有错误。

输入“123FourFive”并退格,产生错误:line 9: [[: 123FourFiv: value too great for base (error token is "123FourFiv")

输入“OneTwo345”和退格,似乎工作正常。

在密码中输入可能期望的符号,然后退格会产生错误:line 9: [[: OneTwo./?: syntax error: invalid arithmetic operator (error token is "./?")

在输入过程中按箭头键也会在退格后产生疯狂的屏幕行为...

如何改进这一点,以便我们屏蔽用户输入,只删除输入的内容?

还是我们在“重新发明轮子”?还有其他东西可以做我已经尝试做的事情(即屏蔽用户输入以在 bash 脚本中获取密码以将其放入变量中)?

用户环境是带有 Cinnamon 的 Linux Mint 19.3。

#!/bin/bash

printf "\n\tPlease enter password: "
    # mask the input for the password by @SiegeX and @mklement0 (https://stackoverflow.com/questions/4316730)
    while IFS= read -r -s -n1 char; do
        [[ -z "${char}" ]] && { printf '\n'; break; } # ENTER pressed; output \n and break.
        if [[ "${char}" == $'\x7f' ]]; then # backspace was pressed
            # @nooblag, only delete for length of entered chars?
            if [[ "${password}" -lt "${#password}" ]]; then printf '\b \b'; fi # erase one '*' to the left.
            [[ -n $password ]] && password=${password%?} # remove last char from output variable
        else
            # add typed char to output variable
            password+="${char}"
            # print '*' in its stead
            printf '*'
        fi
    done

printf "\tPassword: ${password}\n\n"

更新: askpass 建议 here 几乎可以满足我的要求,但是如果用户尝试使用 Ctrl+C 中止/杀死它,它会弄乱终端...

【问题讨论】:

标签: bash input passwords masking


【解决方案1】:

这可能是解决方案!取自here

#!/bin/bash
#
# Read and echo a password, echoing responsive 'stars' for input characters
# Also handles: backspaces, deleted and ^U (kill-line) control-chars
#
unset PWORD
PWORD=
echo -n 'password: ' 1>&2
while true; do
  IFS= read -r -N1 -s char
  # Note a NULL will return a empty string
  # Convert users key press to hexadecimal character code
  code=$(printf '%02x' "'$char") # EOL (empty char) -> 00
  case "$code" in
  ''|0a|0d) break ;;   # Exit EOF, Linefeed or Return
  08|7f)  # backspace or delete
      if [ -n "$PWORD" ]; then
        PWORD="$( echo "$PWORD" | sed 's/.$//' )"
        echo -n $'\b \b' 1>&2
      fi
      ;;
  15) # ^U or kill line
      echo -n "$PWORD" | sed 's/./\cH \cH/g' >&2
      PWORD=''
      ;;
  [01]?) ;;                        # Ignore ALL other control characters
  *)  PWORD="$PWORD$char"
      echo -n '*' 1>&2
      ;;
  esac
done
echo
echo $PWORD

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-09-23
    • 1970-01-01
    • 1970-01-01
    • 2019-05-02
    • 2017-12-20
    • 1970-01-01
    • 1970-01-01
    • 2018-04-23
    相关资源
    最近更新 更多