应用程序如何记住一段时间的身份验证?

应用程序如何记住一段时间的身份验证?

在 Linux 中,有些应用程序能够记住身份验证一段时间。例如,

  • 当我们提供密码来挂载分区时,文件管理器会记住身份验证一段时间。如果我们在挂载第一个分区后立即挂载另一个分区,它不会要求输入密码。

  • 终端应用程序中,如果我们执行某些任务并提供密码,则如果该任务在一定时间段内执行,sudo它将不会要求执行下一步操作。sudo

此功能如何实现?如何让我的应用程序记住根身份验证?

答案1

让程序“记住”某件事很容易:将其写入某个文件,然后稍后再读回。这就是所有设置/首选项的工作方式。(就此而言,这就是定期文件工作。)

(它们可能以文件形式存储在~/.config/磁盘上;以文件形式存储在 RAM 中/run;以抽象设置存储形式存储在 GConf 或 Windows 注册表中;情况各不相同。)

你的例子相关程序/服务不会记住身份验证细节,而只会记住最近身份验证成功(并且操作最终被允许)的事实 - 换句话说,授权。

  • 通过 GUI 安装磁盘时,安装请求将发送到移动U盘,然后询问波尔基特进行确认。(“嘿,用户 X 正在尝试安装磁盘 Y,可以吗?”)

    由于 polkit 是一个永久运行的服务,它会在进程自己的内存中(一个链接列表 (GList))完全跟踪最近的身份验证。您可以src/polkitbackend在其中搜索单词temporary_authorization

    如果你正在实现相同的功能,一个简化的示例是:

    authorizations = list()
    ...
    authorizations.append({user: "niyasc",
                           action: "mount drive",
                           expires: time.now() + 3600})
    

    你的程序还可以使用 polkit

  • 须藤另一方面, 是一个一次性工具,因此它在外部存储相同的信息——与 下的文件相同(/var)/run/sudo/ts。比较文件的“上次修改”时间戳以查看它是否足够新,并在每次使用后更新。

    # ls -l /run/sudo/ts
    total 4
    -rw------- 1 root grawity 80 Jul 29 12:15 /run/sudo/ts/grawity
    

    两种情况下的算法大致如下:

    def check_authorization(user) {
        if has_old_authorization(user) {
            expires = read_authorization(user);
            if expires > time.now() {
                return true;
            }
        }
        success = ask_for_authentication(user);
        if success {
            store_authorization(user, expires=time.now()+3600);
        }
        return success;
    }
    

还有其他“记住身份验证”的方法,但它们都归结为在文件中存储一堆字节:

  • 许多基于网络的应用程序(例如 Thunderbird 或 Outlook 等邮件客户端)实际上将用户名和密码本身直接存储在磁盘上。一个简单的示例是 ~/.netrc 文件:

    machine imap.example.com
        login [email protected]
        password foobar
    

    通常在存储之前会进行加密(应用程序可能使用 GNOME-Keyring 等操作系统功能,或者可能支持“主密码”),但最终只是可以存储在文件中的一段数据

  • 许多网络基于 cookie 的应用程序使用 cookie 来记住您已登录的事实。登录后,服务器会要求您的浏览器记住“session_id=SGVsbG8gd29ybGQh”之类的内容,并在每次下次访问时将其发回。浏览器通常有一个基于文本或所有网站发布的所有 cookie 的基于 SQLite 的数据库(“cookie jar”)。

    服务器也有一个‘会话’数据库,其中包含有关每个已发布的 cookie 的信息,因此当它收到相同的“session_id=SGVsbG8gd29ybGQh”时,它就知道你是 niyasc:

    SESSION_ID         USERNAME   ISSUED          EXPIRES
    SGVsbG8gd29ybGQh   niyasc     Jul 29, 11:47   Aug 29, 11:47
    6kJnRcg4KBAPrMJ4   fred       Jun 14, 22:13   Sep 14, 22:13
    ...
    
  • 某些网络协议(例如 Kerberos 或 SAML)使用一种称为“票据”或“令牌”的 Cookie 形式,这些 Cookie他们自己有关于何时签发以及为谁签发的信息。(它们还由身份验证服务进行数字签名作为证明。)这还允许“身份验证”服务器和“应用程序”服务器分开,以提高安全性。

  • 然而,其他协议(例如 SSH 或 SSL/TLS)使用数字签名 - 客户端根本没有密码,而是拥有一个私钥对(通常是 RSA 或 [EC]DSA),它也作为文件存储在磁盘上 - 例如文件~/.ssh/id_rsa

    对于每个连接,服务器都会发送一个“挑战”(一系列随机字节);客户端使用其私钥对其进行签名;然后服务器验证签名并检查它是否由其中一个“允许”的密钥签名。

答案2

这是因为缓存。缓存的概念非常简单。它是一种比普通磁盘快得多的内存。每当你想要查找某个东西或运行某个命令时,CPU 首先接触缓存,如果它在缓存中,那么提取速度非常快。但如果不在,那么它会进入普通内存并查找然后提取,整个过程需要一些时间。

Linux 理解并使用缓存的概念。首次访问文件后,内容将保存在内存中(如果可用)以供将来使用。下次运行同一命令时,CPU 只需从内存中获取内容,而无需读取任何内容。因此,它提高了整体执行速度。

假设你打开终端,然后输入命令密码。首次运行需要一些时间来显示当前工作目录。现在运行密码再次,这次你会看到执行非常快。因为在第二次运行时,当前工作目录已经保存在内存中。CPU 只需获取信息即可。

希望你现在已经有了一些想法。

谢谢。

相关内容