将 root 权限传递给 Python 中的 "os" 命令

Pass root privilege to "os" commands in Python

我正在向 PyQt5 应用程序添加功能。此新功能涉及复制、链接和删除 可能 受保护目录中的文件(和链接),因此 os.symlinkshutil.copyfile 等命令将失败。

当然,主应用程序 运行 没有 root 权限(并且要求用户这样做是不可能的),所以我需要一个解决方法。

第一件事当然是将关键代码包装在 try/except 块中并调查任何异常。如果事实证明缺少 root 权限是问题所在,我会在对话框中询问密码(大概只要当前对话框处于活动状态就存储密码)。

但我不确定如何使用 root 密码重复步骤。我强烈希望在 Python 域中执行此操作(或者 Qt 是否提供对文件操作的一些支持?我敢打赌,但我找不到它)。我认为应该可以通过在 shell 命令中执行文件操作并以某种方式将密码传递给它,但是由于 Python 和 PyQt 旨在保护程序员免受 OS 差异我宁愿避开那条路线。

一些伪代码应该可以清楚地说明问题:

def my_copy(source, dest):
    try:
        os.path.symlink(source, dest)
    except: # check for permission problem:
        # use dialog to ask for password
        # repeat the symlink procedure with password

用计数器将 try/except 代码包裹在一个循环中:

def my_copy(source, dest):
    for attempts in [1, 2]:
        try:
            os.path.symlink(source, dest)
            # we succeeded, so don't try any more
            break
        except: # check for permission problem:
            if attempts == 1:
                # use dialog to ask for password
                # repeat the symlink procedure with password
            else:
                 # we already tried as root, and failed again
                 break

你在这里尝试做的事情在大多数现代操作系统上基本上是不可能的,这是有充分理由的。

想象一个典型的 macOS 或 Windows 用户希望能够通过使用指纹 reader 而不是输入密码来进行身份验证。或者盲人用户。或者有人对你的应用程序以明文形式将密码存储在非内核内存中的 Python 字符串中(更不用说在 Windows 对话框中,其事件可以被任何进程挂钩)。这就是现代平台带有 libPAM/XSSO, Authorization Services 这样的框架的原因。等等

Windows 和 POSIX,甚至 macOS 和 Linux 之间的提权方式也大不相同,更不用说这么快了不断发展,据我所知,没有跨平台框架可以做到这一点。

事实上,大多数系统从一开始就不鼓励应用程序驱动的权限升级。在 Windows 上,您经常要求 OS 向 运行 一个具有更高权限的辅助应用程序(然后 OS 将应用适当的策略并决定请求什么)。在 macOS 上,您通常会编写一个 LaunchServices 守护进程,您在安装时(使用特殊的安装程序 API)而不是 运行 时获得许可。对于传统的非服务器 POSIX 应用程序,您通常会做类似的事情,但是使用 setuid 帮助程序,您可以在安装时创建它,因为安装 运行s作为根。对于传统的 POSIX 服务器,您通常以 root 身份启动,然后在分叉并执行类似的辅助守护进程后删除 privs。

如果所有这些工作看起来比您想处理的要多得多……好吧,老实说,这可能就是我们的意图。 OS 设计人员不希望应用程序设计人员引入安全漏洞,因此他们确保您必须了解平台想要什么以及如何使用它而不是反对它,然后您甚至可以 尝试 来执行诸如移动您没有权限的文件之类的操作。