简单的 if 语句检查行是否在文件中

简单的 if 语句检查行是否在文件中

我正在尝试为我的脚本创建一个非常简单的登录控制台,这只是为了好玩,看看它是否有效。

基本上,我认为可能的情况是这样的。

如果存在某种模式,我将读取文件$password_file和文件$username_file。假设我在两个文件的第一行(或任何行)中都输入了“bryan”。现在我想在脚本继续执行其基本功能之前放置这段代码。

echo "Welcome"
echo "Ur username is:"
read username
echo "Ur password is:"
read password
if sed -n "/$username/" $username_file; then
    if sed -n "/$password" $password_file; then

else
    exit;
    fi
fi

我想我在这里做错了什么,因为我收到一个错误,在附近有一个意外的标记else

所以基本上我只希望 if 语句首先读取$username_file,然后如果模式bryan在该文件中,我希望它读取$password_file,之后我希望脚本继续转到我编写的正常脚本开始的某一行。

我希望我解释得正确,以便你能理解我。

(我还可以通过添加类似的内容来扩展这个小脚本,如果用户名或密码不在该文件中,则回显“未找到,脚本将重新加载再试一次”。)

答案1

问题是 bash 将其解释为;在该行中then; else放入一个。:

如果每行仅由您要查找的内容组成,您也可以使用fgrep -x

echo "Welcome"
echo "Username:"
read username
echo "Password:"
read password
if ! (fgrep -qx "$username" $username_file && fgrep -qx "$password" $password_file); then
    exit
fi

答案2

这里存在一些问题:

  • then内部语句的部分中没有命令if,这导致了您看到的错误。您可以通过:在该then部分中使用占位符伪命令或否定测试并省略该else部分来解决此问题。

  • sed命令也是无效的,而且它无论如何都不是适合这项工作的工具。在文件中搜索特定行grep通常是首选命令。在这种情况下,grep -Fx执行纯文本 ( -F) 整行 ( -x) 匹配可能是最好的选择。

  • if ... if ... else 逻辑也关闭了。我假设您想在未找到用户名或密码时退出,但(如所写)该else子句仅在用户名曾是成立,密码不对。要修复此问题,请使用如下方法:

    if ! grep -Fxq "$username" "$username_file" || ! grep -Fxq "$password" "$password_file"; then
        echo "Invalid login"
        exit 1
    fi
    

    或者可能:

    if ! grep -Fxq "$username" "$username_file"; then
        echo "User $username not found"
        exit 1
    elif ! grep -Fxq "$password" "$password_file"; then
        echo "Incorrect password"
        exit 1
    fi
    
  • 实际上,这种逻辑仍然是错误的;它只检查用户名和密码是否存在于各自的文件中,而不是检查它们是否在一起。我可以输入我的密码和别人的用户名,它就会让我进入。您需要确保用户名和密码在一起,可能只需将它们放在同一个文件中并同时搜索它们即可:

    if ! grep -Fxq "$username:$password" "$user_file" ; then
        echo "Invalid login"
        exit 1
    fi
    
  • 最后,存储密码(即使是在只有 root 可以读取的文件中)是一个非常糟糕的主意——对密码进行哈希处理并存储哈希值。实际上,为了获得最佳安全性,您应该使用加盐哈希,这会使搜索变得复杂——您必须找到用户条目,找出与其密码一起使用的盐,使用相同的盐对用户输入的内容进行哈希处理,然后将其与文件中的内容进行比较。这反过来意味着它将grep -Fx不再起作用,我们需要grep在进行模式匹配的模式下使用,并小心避免用户名中的模式元字符......

假设您有 openssl 可用,下面是一个简单的尝试:

echo "Welcome"
read -p "Ur username is: " username
if [[ "$username" =~ "[][(){}*.?+|^\$]" ]]; then
    echo "Illegal character in username"
    exit 1
fi

# Find the user's record in the file
user_record="$(grep "^$username:" "$user_file")"
if [[ -z "$user_record" ]]; then
    echo "User $username not found"
    exit 1
fi
# Parse out the user's hashed password and salt
recordedhash="${user_record#*:}"
if [[ "$recordedhash" != '$1$'* ]]; then
    echo "Invalid user record for $username"
    exit 1
fi
salt="${recordedhash#\$1\$}"
salt="${salt%\$*}"

read -p "Ur password is: " -s password
echo
if [[ "$(printf "%s" "$password" | openssl passwd -1 -stdin -salt "$salt")" != "$recordedhash" ]]; then
    echo "Incorrect password"
    exit 1
fi

要在用户文件中创建条目,请使用以下命令:

read -p "Ur username is: " username
if [[ "$username" =~ "[][(){}*.?+|^\$]" ]]; then
    echo "Illegal character in username"
    exit 1
fi
read -p "Ur password is: " -s password
echo
hashedpw="$(printf "%s" "$password" | openssl passwd -1 -stdin)"
user_record="$username:$hashedpw"
# Then do something to add $user_record to the file, or replace the existing record if there is one

我不保证上述内容没有错误;我只是对其进行了一些非常基本的测试。

答案3

这听起来像XY问题

你为什么要这样做?正如@Gordon Davisson 的出色回答所示,这比你想象的要困难。不仅有安全问题需要考虑,而且 unix 密码并非全部存储在 /etc/passwd 中。因此,要么你必须重做很多事情聚丙烯酰胺已经如此。

一个简单的想法,也许你想做类似的事情

PASSED=$(su $USER -c “echo LOGIN”)

如果 su 失败,则表示他们没有密码。然后 PASSED 将为空白。通过使用 su,您将完成所有常规密码例程(如果需要,使用 pam),并且您无需维护任何内容。

相关内容