应用程序如何记住身份验证?

niy*_*asc 4 linux password-management authentication

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

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

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

这个功能是如何实现的?如何让我的应用程序记住 root 身份验证?

use*_*686 6

让程序“记住”某些东西很容易:将它写入某个文件中,然后稍后再读回来。这就是所有设置/首选项的工作方式。(就此而言,这是常规文件的工作方式。)

(它们可能存储为~/.config/磁盘上的文件;RAM 中的文件/run;抽象设置存储,如 GConf 或 Windows 注册表;它会有所不同。)

您的两个示例中,相关程序/服务不记得身份验证详细信息,而只记住最近身份验证成功的事实(并且最终允许该操作)——换句话说,授权。

  • 当通过 GUI 挂载磁盘时,挂载请求被发送到UDisks,然后请求polkit确认。(“嘿,用户 X 正在尝试挂载磁盘 Y,是否允许?”)

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

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

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

    您的程序也可以使用 polkit

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

    # ls -l /run/sudo/ts
    total 4
    -rw------- 1 root grawity 80 Jul 29 12:15 /run/sudo/ts/grawity
    
    Run Code Online (Sandbox Code Playgroud)

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

    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;
    }
    
    Run Code Online (Sandbox Code Playgroud)

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

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

    machine imap.example.com
        login niyasc@example.com
        password foobar
    
    Run Code Online (Sandbox Code Playgroud)

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

  • 许多基于Web的应用程序使用 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
    ...
    
    Run Code Online (Sandbox Code Playgroud)
  • 某些网络协议(例如 Kerberos 或 SAML)使用一种称为“票证”或“令牌”的 cookie 形式,这些 cookie本身具有关于何时发行以及为谁发行的信息。(它们也由身份验证服务进行数字签名作为证明。)这还允许“身份验证”服务器和“应用程序”服务器分开以提高安全性。

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

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