在 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 只需获取信息即可。
希望你现在已经有了一些想法。
谢谢。