让用户仅使用 GUI(隐藏终端)输入 bash 脚本密码的正确方法

让用户仅使用 GUI(隐藏终端)输入 bash 脚本密码的正确方法

我编写了一个 bash 脚本,专门使用 kdialog 与用户交互。它是从“.desktop”文件启动的,因此用户永远不会看到终端。它看起来 100% 像一个 GUI 应用程序(尽管它只是一个 bash 脚本)。它仅在 KDE 中运行(Kubuntu 12.04)。

我唯一的问题是安全处理密码输入并且很方便。我找不到令人满意的解决方案。

剧本是设计以普通用户身份运行,并在第一次需要 sudo 命令时提示输入密码。这样,大多数命令(不需要 sudo 权限的命令)都以普通用户身份运行。会发生什么(当从终端运行脚本时)是提示用户输入一次密码,默认 sudo 超时允许脚本完成,包括任何其他 sudo 命令,而无需再次提示用户。这也是我希望它在 GUI 后面运行时的工作方式。

主要问题是使用kdesudo标准 GUI 方式启动我的脚本意味着整个脚本由 root 用户执行。因此文件所有权被分配给 root 用户,我无法依赖~/路径,而且许多其他事情都不太理想。以 root 用户身份运行整个脚本只是一个非常不令人满意的解决方案,我认为这是一种不好的做法。

我很感激任何可以让用户通过 GUI 输入一次 sudo 密码而不以 root 身份运行整个脚本的想法。谢谢。

答案1

sudo选项-A允许您指定一个要求输入密码的辅助程序(在 SUDO_ASKPASS 变量中)。

创建一个询问密码的脚本(myaskpass.sh):

#!/bin/bash
zenity --password --title=Authentication

然后在脚本的开头插入此行:

export SUDO_ASKPASS="/path/to/myaskpass.sh"

并将所有出现的替换为sudo <command>

sudo -A <command>

您可以使用任何您想要的密码询问程序来代替zenity。我必须将其封装在脚本中,因为 SUDO_ASKPASS 必须指向一个文件,因此它无法与--password所需的选项一起使用zenity

如果它从命令行运行,或者您选择,上述操作将非常有效在终端中运行在文件管理器中双击脚本文件后,但如果选择跑步或者尝试从 .desktop 文件启动它,每次sudo都会再次要求输入密码。


如果你根本不想要终端窗口,你可以将密码存储在变量中并将其通过管道传输到sudo -S。也许存在一些安全问题,但我认为这是相当安全的(阅读评论这个答案)。

在脚本的开头插入此行:

PASSWD="$(zenity --password --title=Authentication)\n"

并将所有出现的替换为sudo <command>

echo -e $PASSWD | sudo -S <command>

答案2

这是基于 Eric Carvalho 的出色回答。我发布它是为了详细说明我遇到的问题。具体来说,使用这个时,通常的 sudo 超时(例如 15 分钟)会丢失。我的脚本有超过 50 个 sudo 命令,现在会提示用户输入密码 50 次以上!

以下是解决方案所有部分的完整工作示例。它由一个 bash 脚本、一个 Eric 建议的“myaskpass”脚本和一个“.desktop”文件组成。整个东西应该是 100% GUI(完全没有终端交互),因此 .desktop 文件是必不可少的(据我所知)。

$ cat myaskpass.sh 
#!/bin/bash
kdialog --password "Please enter your password: "
exit 0


$ cat askpasstest1.desktop 
#!/usr/bin/env xdg-open
[Desktop Entry]
Comment=SUDO_ASKPASS tester1
Exec=bash /home/user/test/askpasstest1.sh
GenericName=SUDO_ASKPASS tester1
Name=SUDO_ASKPASS tester1
NoDisplay=false
Path[$e]=
StartupNotify=true
Terminal=false
TerminalOptions=
Type=Application
Categories=Application;Utility;
X-KDE-SubstituteUID=false
X-KDE-Username=

还有一个测试脚本本身。使用此解决方案时,它将要求您输入两次密码。(通常,由于默认的 sudo 超时,它只会询问一次。)

#!/bin/bash

sudo -k
SUDO_ASKPASS="/home/user/test/myaskpass.sh" sudo -A touch filemadeas_askpass1
touch filemadeas_regularuser1
SUDO_ASKPASS="/home/user/test/myaskpass.sh" sudo -A touch filemadeas_askpass2
touch filemadeas_regularuser2
ls -la filemadeas* > /home/user/test/fma.log
kdialog --title "Files Created" --textbox /home/user/test/fma.log 640 480
sudo rm filemadeas_*
rm fma.log

exit 0

答案3

以下脚本通过命令行、桌面文件或双击运行,仅要求输入一次密码,并且命令模式sudo -Sp '' <your command here> <<<${sudo_password}可以在文件中的任何位置多次使用:

    # get sudo password
    sudo_password=$( gksudo --print-pass --message="Provide permission to make system changes: Type your password or press Cancel." -- : 2>/dev/null )
    # check for null entry or cancellation
    if [[ ${?} != 0 || -z ${sudo_password} ]]
    then
        exit 4
    fi
    if ! sudo -kSp '' [ 1 ] <<<${sudo_password} 2>/dev/null
    then
        exit 4
    fi
    # command
    sudo -Sp '' gedit "/etc/hosts" <<<${sudo_password}

相关内容