0

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

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

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

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

一些伪代码应该清楚地说明这个问题:

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
4

2 回答 2

1

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

想象一个典型的 macOS 或 Windows 用户希望能够通过使用指纹读取器而不是输入密码来进行身份验证。或者是盲人用户。或者有人对您的应用程序以纯文本形式将密码存储在非内核内存中的 Python 字符串中(更不用说在其事件可以被任何进程挂钩的 Windows 对话框中)抱有合理的偏执。这就是为什么现代平台带有一个框架,如libPAM/XSSO授权服务。等等

Windows 和 POSIX 甚至 macOS 和 Linux 之间的权限提升工作方式如此不同,更不用说发展如此迅速,据我所知,没有跨平台框架可以做到这一点。

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

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

于 2018-07-30T18:56:59.973 回答
0

使用计数器将 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
于 2018-07-30T17:43:28.213 回答