<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>潘锦的空间 &#187; MFA</title>
	<atom:link href="https://www.phppan.com/tag/mfa/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.phppan.com</link>
	<description>SaaS SaaS架构 团队管理 技术管理 技术架构 PHP 内核 扩展 项目管理</description>
	<lastBuildDate>Sat, 25 Apr 2026 00:56:17 +0000</lastBuildDate>
	<language>zh-CN</language>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=3.9.40</generator>
	<item>
		<title>架构师必备：MFA 了解一下</title>
		<link>https://www.phppan.com/2024/12/architect-must-know-mfa-introduction/</link>
		<comments>https://www.phppan.com/2024/12/architect-must-know-mfa-introduction/#comments</comments>
		<pubDate>Sat, 07 Dec 2024 01:34:28 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[架构和远方]]></category>
		<category><![CDATA[MFA]]></category>
		<category><![CDATA[安全]]></category>
		<category><![CDATA[安全架构]]></category>
		<category><![CDATA[架构师]]></category>

		<guid isPermaLink="false">http://www.phppan.com/?p=2304</guid>
		<description><![CDATA[1. 引言 还记得 2023 年 GitHub 强制推行多因子认证（MFA）的那一刻吗？从 3 月开始，Git [&#8230;]]]></description>
				<content:encoded><![CDATA[<h1 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">1. 引言</span></h1>
<p style="color: #000000;" data-tool="mdnice编辑器">还记得 2023 年 GitHub 强制推行多因子认证（MFA）的那一刻吗？从 3 月开始，GitHub 分阶段要求用户启用 MFA，并在年底前全面完成覆盖，这让全球开发者不得不重新审视身份安全的重要性。</p>
<p style="color: #000000;" data-tool="mdnice编辑器">现在我们登录 Github ，除了要输入密码，还需要完成一个额外的验证步骤，比如输入手机上的动态验证码，或者通过手机上的身份验证器（Authenticator App）确认登录。这种看似繁琐的体验已经成为各大云厂商产品的标配。不仅是 GitHub，像 AWS、阿里云、腾讯云等云厂商也几乎都要求在敏感操作时使用多因子认证（MFA），以确保账户安全。</p>
<p style="color: #000000;" data-tool="mdnice编辑器">这种举措不仅保护了平台上的代码和账户安全，更体现了现代身份管理技术的趋势，今天，我们就从 GitHub 强制 MFA 的案例切入，了解 MFA 及 Google Authenticator 的实现原理。</p>
<h1 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">2. 什么是 MFA/2FA</span></h1>
<p style="color: #000000;" data-tool="mdnice编辑器">在探讨 MFA 之前，我们需要理解身份验证的本质。<strong style="color: #0e88eb;">身份验证</strong>是确认某人或某物的身份是否属实的过程。无论是通过密码登录 Gmail，还是刷身份证进入火车站，身份验证的核心都是确保「你是你自称的那个人」。</p>
<p style="color: #000000;" data-tool="mdnice编辑器">然而，传统的基于密码的身份验证模式存在诸多隐患：</p>
<ul class="list-paddingleft-1" style="color: #000000;">
<li>
<section style="color: #010101;"><strong style="color: #0e88eb;">密码过于简单</strong>：许多人使用诸如“123456”或“password”这样的弱密码。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #0e88eb;">密码重复使用</strong>：用户往往将同一个密码应用于多个网站，一旦一个账户泄露，其它账户也岌岌可危。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #0e88eb;">钓鱼攻击和暴力破解</strong>：黑客通过欺骗或技术手段轻易获取用户密码。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #0e88eb;">中间人攻击</strong>：在不安全的网络环境中，密码可能被拦截。</section>
</li>
</ul>
<p style="color: #000000;" data-tool="mdnice编辑器">这些问题导致密码的安全性备受质疑，因此需要额外的保护层，MFA 由此应运而生。</p>
<h2 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">2.1 MFA：不是多一个步骤，而是多一层防护</span></h2>
<p style="color: #000000;" data-tool="mdnice编辑器">MFA，Multi-Factor Authentication，多因子认证，是一种身份验证方法，要求用户提供多个独立的身份验证因素来完成登录或访问。传统的身份认证只依赖单一密码，MFA 则通过引入额外的验证步骤，极大地提升了账户安全性。</p>
<p style="color: #000000;" data-tool="mdnice编辑器">在 MFA 中，通常会结合以下三类验证因素：</p>
<ul class="list-paddingleft-1" style="color: #000000;">
<li>
<section style="color: #010101;"><strong style="color: #0e88eb;">你知道的东西</strong>：密码、PIN 码、答案问题等。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #0e88eb;">你拥有的东西</strong>：动态验证码（通过手机或硬件设备生成）、安全令牌、智能卡、U 盾等。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #0e88eb;">你自身的特征</strong>：生物特征验证，如指纹、面部识别、虹膜扫描等。</section>
</li>
</ul>
<p style="color: #000000;" data-tool="mdnice编辑器"><strong style="color: #0e88eb;">MFA 的意义</strong>在于，即便攻击者获得了你的密码，由于缺少额外的验证因素，他们依然无法轻易访问你的账户。例如，登录 GitHub 时，即使密码被泄露，攻击者若没有你的手机或安全密钥，仍然无法完成登录。</p>
<p style="color: #000000;" data-tool="mdnice编辑器">毕竟，密码泄露已经成为网络攻击中最常见的手段，而 MFA 则为用户的账户增加了第二道甚至第三道锁。</p>
<h2 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">2.2 2FA</span></h2>
<p style="color: #000000;" data-tool="mdnice编辑器"><strong style="color: #0e88eb;">2FA</strong> 是<strong style="color: #0e88eb;">MFA</strong> 的一种特殊形式，它仅使用<strong style="color: #0e88eb;">两种不同的验证因素</strong>来完成认证。简单来说，2FA 是 MFA 的一个子集。</p>
<p style="color: #000000;" data-tool="mdnice编辑器">例如：</p>
<ul class="list-paddingleft-1" style="color: #000000;">
<li>
<section style="color: #010101;">登录时输入密码（第一个验证因素：你知道的东西）。</section>
</li>
<li>
<section style="color: #010101;">然后输入手机上的动态验证码（第二个验证因素：你拥有的东西）。</section>
</li>
</ul>
<p style="color: #000000;" data-tool="mdnice编辑器">值得注意的是，两种不同的验证因素是<strong style="color: #0e88eb;">类别的不同</strong>，像以前有一种策略是需要提供密码和安全问题答案，这是单因素身份验证，因为这两者都与「你知道的东西」这个因素有关。</p>
<p style="color: #000000;" data-tool="mdnice编辑器">在大多数应用中，2FA 已经足够满足安全需求，因此它是目前最常见的多因子认证实现方式。</p>
<h1 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">3. 为什么 MFA 如此重要？</span></h1>
<h2 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">1. 密码不再安全</span></h2>
<p style="color: #000000;" data-tool="mdnice编辑器">随着技术的进步，密码破解的门槛越来越低。攻击者可以通过以下方式轻松破解密码：</p>
<ul class="list-paddingleft-1" style="color: #000000;">
<li>
<section style="color: #010101;"><strong style="color: #0e88eb;">暴力破解</strong>：通过快速尝试各种可能的密码组合。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #0e88eb;">数据泄露</strong>：黑客通过暗网购买被泄露的用户名和密码。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #0e88eb;">钓鱼攻击</strong>：通过伪装成合法网站诱骗用户输入密码。</section>
</li>
</ul>
<p style="color: #000000;" data-tool="mdnice编辑器">在这种背景下，仅靠密码保护账户变得极为不可靠。MFA 通过引入多层保护，从根本上提升了安全性。</p>
<h2 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">2. 提高攻击成本</span></h2>
<p style="color: #000000;" data-tool="mdnice编辑器">MFA 的最大优势在于，它大幅提高了攻击者的攻击成本。例如，攻击者即便成功窃取了用户密码，也需要物理接触用户的手机或破解生物特征才能完成登录。这种额外的复杂性往往会使攻击者放弃目标。</p>
<h2 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">3. 应对多样化的威胁</span></h2>
<p style="color: #000000;" data-tool="mdnice编辑器">MFA 可以有效抵御多种网络威胁，包括：</p>
<ul class="list-paddingleft-1" style="color: #000000;">
<li>
<section style="color: #010101;"><strong style="color: #0e88eb;">凭证填充攻击</strong>：即使用泄露的密码尝试登录多个账户。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #0e88eb;">中间人攻击</strong>：即便密码在传输中被窃取，攻击者仍需第二个验证因素。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #0e88eb;">恶意软件</strong>：即使恶意软件记录了用户输入的密码，也无法破解动态验证码。</section>
</li>
</ul>
<h1 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">4. MFA/2FA 的工作过程和形式</span></h1>
<h2 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">4.1 MFA 验证的形式</span></h2>
<p style="color: #000000;" data-tool="mdnice编辑器">MFA 形式多样，主要有如下的一些形式：</p>
<ol class="list-paddingleft-1" style="color: #000000;">
<li>
<section style="color: #010101;"><strong style="color: #0e88eb;">基于短信的验证</strong>：用户在输入密码后，会收到一条包含验证码的短信。虽然方便，但短信验证并非绝对安全，因为短信可能被拦截或通过 SIM 卡交换攻击（SIM Swapping）被窃取。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #0e88eb;">基于 TOTP（时间同步一次性密码）的验证</strong>：像 Google Authenticator 这样的应用程序可以生成基于时间的动态密码。这种方式更安全，因为动态密码仅在短时间内有效，且无需网络传输。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #0e88eb;">硬件令牌</strong>：硬件令牌是专门生成动态密码的物理设备。例如银行常用的 USB 令牌，用户需要插入电脑才能完成验证。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #0e88eb;">生物特征验证</strong>：指纹、面部识别和视网膜扫描是最常见的生物特征验证方式。这种验证方式非常直观，但存在用户数据隐私的争议。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #0e88eb;">基于位置的验证</strong>：通过 GPS 或 IP 地址限制用户只能在特定位置登录。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #0e88eb;">基于行为的验证</strong>：通过分析用户的打字节奏、鼠标移动轨迹等行为特征来确认身份。</section>
</li>
</ol>
<h2 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">4.2 2FA 如何工作？</span></h2>
<p style="color: #000000;" data-tool="mdnice编辑器">双因素身份验证的核心理念是：即使攻击者获得了用户的密码，他仍然需要通过第二道验证关卡才能访问账户。以下是 2FA 的典型工作流程：</p>
<ol class="list-paddingleft-1" style="color: #000000;">
<li>
<section style="color: #010101;"><strong style="color: #0e88eb;">第一道验证：用户输入用户名和密码</strong>：用户通过密码证明「知道的内容」，这是第一道验证因素。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #0e88eb;">第二道验证：动态代码或生物特征识别</strong>：系统会向用户发送一个一次性验证码（如短信、电子邮件或 Google Authenticator 生成的代码），或者要求用户提供指纹或面部识别。这是「拥有的东西」或「自身的特征」的验证。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #0e88eb;">验证成功，授予访问</strong>：如果两道验证都通过，用户即可成功登录。</section>
</li>
</ol>
<p style="color: #000000;" data-tool="mdnice编辑器">如当你登录阿里云时，输入密码后需要打开阿里云的 APP，输入 MFA 的验证码。</p>
<h1 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">5. MFA 的局限性</span></h1>
<p style="color: #000000;" data-tool="mdnice编辑器">尽管 MFA 极大地提高了账户安全性，但它并非万能。有如下的一些局限性：</p>
<ol class="list-paddingleft-1" style="color: #000000;">
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">用户体验问题</strong>：对于技术不熟练的用户来说，设置和使用 MFA 应用程序门槛比较高。此外，每次登录需要额外的验证步骤，也可能降低用户体验。</p>
</section>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">成本问题</strong>：企业需要支付额外的费用来实施 MFA。例如短信验证需要支付短信发送费用，而硬件令牌的采购和分发也需要额外开支。</p>
</section>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">并非百分百安全</strong>：MFA 虽然有效，但并非无懈可击。例如：</p>
</section>
<ul class="list-paddingleft-1">
<li>
<section style="color: #010101;">短信验证可能被攻击者通过 SIM 卡交换攻击破解。</section>
</li>
<li>
<section style="color: #010101;">恶意软件可能会窃取动态密码。</section>
</li>
<li>
<section style="color: #010101;">高级攻击者甚至可能通过社会工程学手段获取验证码。</section>
</li>
</ul>
</li>
</ol>
<p style="color: #000000;" data-tool="mdnice编辑器">在了解了概念后，我们看一下我们常用的一个 MFA 验证应用 Google Authenticator 的实现原理。</p>
<h1 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">6. Google Authenticator 的实现原理</span></h1>
<p style="color: #000000;" data-tool="mdnice编辑器">在使用 Google Authenticator 进行 2FA 的过程中，验证的过程可以分为以下两个主要阶段：<strong style="color: #0e88eb;">初始化阶段</strong> 和<strong style="color: #0e88eb;">验证阶段</strong>。</p>
<h2 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">6.1 初始化阶段：共享密钥生成与分发</span></h2>
<p style="color: #000000;" data-tool="mdnice编辑器">这是用户首次启用双因素身份验证时发生的过程。在此阶段，服务端生成共享密钥（Secret Key）并通过安全的方式分发给用户的 Google Authenticator 应用。</p>
<ol class="list-paddingleft-1" style="color: #000000;">
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">服务端生成共享密钥</strong>：</p>
</section>
<ul class="list-paddingleft-1">
<li>
<section style="color: #010101;">服务端为用户生成一个随机的共享密钥<code style="color: #0e8aeb;">K</code>（通常是 16~32 个字符的 Base32 编码字符串，例如<code style="color: #0e8aeb;">JBSWY3DPEHPK3PXP</code>）。</section>
</li>
<li>
<section style="color: #010101;">该密钥会作为后续动态密码生成的核心，必须对外保密。</section>
</li>
</ul>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">生成二维码</strong>：</p>
</section>
<ul class="list-paddingleft-1">
<li>
<section style="color: #010101;"><code style="color: #0e8aeb;">Example</code>: 服务提供方的名称。</section>
</li>
<li>
<section style="color: #010101;"><code style="color: #0e8aeb;">username@example.com</code>: 用户的账户。在 github 的场景中这个字段是没有的。</section>
</li>
<li>
<section style="color: #010101;"><code style="color: #0e8aeb;">SECRET=JBSWY3DPEHPK3PXP</code>: 共享密钥。</section>
</li>
<li>
<section style="color: #010101;"><code style="color: #0e8aeb;">issuer=Example</code>: 服务提供方名称（用于显示在 Google Authenticator 中）。</section>
</li>
</ul>
<ul class="list-paddingleft-1">
<li>
<section style="color: #010101;">
<p style="color: #000000;">服务端将共享密钥和其他元信息（如站点名称、用户账户）打包成一个 URL，符合<code style="color: #0e8aeb;">otpauth://</code> 协议格式，例如：</p>
<pre><code style="color: #0e8aeb;">otpauth://totp/Example:username@example.com?secret=JBSWY3DPEHPK3PXP&amp;issuer=Example
</code></pre>
<p style="color: #000000;">其中：</p>
</section>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;">该 URL 会被编码为一个二维码，供用户扫描。</p>
</section>
</li>
</ul>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">用户扫描二维码</strong>：</p>
</section>
<ul class="list-paddingleft-1">
<li>
<section style="color: #010101;">用户使用 Google Authenticator 应用扫描二维码，应用会解析出共享密钥（<code style="color: #0e8aeb;">K</code>）以及站点相关信息，并将其安全存储在手机本地。</section>
</li>
<li>
<section style="color: #010101;">共享密钥在手机端不会传回服务端，所有计算均在本地完成。</section>
</li>
</ul>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">初始化完成</strong>：</p>
</section>
<ul class="list-paddingleft-1">
<li>
<section style="color: #010101;">用户的 Google Authenticator 应用现在可以基于共享密钥<code style="color: #0e8aeb;">K</code> 和当前时间生成动态密码。</section>
</li>
<li>
<section style="color: #010101;">服务端同时将该共享密钥<code style="color: #0e8aeb;">K</code> 绑定到用户账户，并妥善保存以便后续验证使用。</section>
</li>
</ul>
</li>
</ol>
<h2 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">6.2 验证阶段：动态密码的生成与验证</span></h2>
<p style="color: #000000;" data-tool="mdnice编辑器">这是用户登录时的验证过程。在此阶段，客户端和服务端基于相同的共享密钥<code style="color: #0e8aeb;">K</code> 和时间步长计算动态密码，并进行验证。</p>
<h3 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e88eb;">6.2.1 客户端生成动态密码</span></h3>
<ol class="list-paddingleft-1" style="color: #000000;">
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">获取当前时间</strong>：</p>
</section>
<ul class="list-paddingleft-1">
<li>
<section style="color: #010101;">Google Authenticator 应用从设备的系统时间中获取当前的 Unix 时间戳（以秒为单位）。</section>
</li>
</ul>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">将时间戳转换为时间步长</strong>：</p>
</section>
<ul class="list-paddingleft-1">
<li>
<section style="color: #010101;">将时间戳除以时间步长（通常为 30 秒），并取整：</p>
<pre><code style="color: #0e8aeb;">T = floor(currentUnixTime / timeStep)
</code></pre>
<p>例如，当前时间是<code style="color: #0e8aeb;">1697031000</code> 秒，时间步长为 30 秒，则：</p>
<pre><code style="color: #0e8aeb;">T = floor(1697031000 / 30) = 56567700
</code></pre>
</section>
</li>
</ul>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">计算 HMAC-SHA-1 哈希值</strong>：</p>
</section>
<ul class="list-paddingleft-1">
<li>
<section style="color: #010101;">Google Authenticator 将时间步长<code style="color: #0e8aeb;">T</code> 转换为 8 字节的 Big-endian 格式（例如<code style="color: #0e8aeb;">0x00000000056567700</code>）。</section>
</li>
<li>
<section style="color: #010101;">使用共享密钥<code style="color: #0e8aeb;">K</code> 和时间步长<code style="color: #0e8aeb;">T</code> 作为输入，计算 HMAC-SHA-1 哈希值：</p>
<pre><code style="color: #0e8aeb;">HMAC = HMAC-SHA-1(K, T)
</code></pre>
<p>结果是一个 20 字节（160 位）的哈希值。</section>
</li>
</ul>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">截断哈希值</strong>：</p>
</section>
<ul class="list-paddingleft-1">
<li>
<section style="color: #010101;">根据 HMAC 的最后一个字节的低 4 位，确定一个偏移量<code style="color: #0e8aeb;">offset</code>。</section>
</li>
<li>
<section style="color: #010101;">从 HMAC 中偏移量开始，提取连续 4 个字节，生成动态二进制码（Dynamic Binary Code，DBC）。</section>
</li>
<li>
<section style="color: #010101;">对提取的 4 字节数据按无符号整数格式解释，并将最高位（符号位）置零，确保结果为正整数。</section>
</li>
</ul>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">取模生成动态密码</strong>：</p>
</section>
<ul class="list-paddingleft-1">
<li>
<section style="color: #010101;">对动态二进制码取模<code style="color: #0e8aeb;">10^6</code>，生成 6 位数字密码：</p>
<pre><code style="color: #0e8aeb;">OTP = DBC % 10^6
</code></pre>
<p>例如，计算结果为<code style="color: #0e8aeb;">123456</code>。</section>
</li>
</ul>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">显示动态密码</strong>：</p>
</section>
<ul class="list-paddingleft-1">
<li>
<section style="color: #010101;">Google Authenticator 将生成的 6 位动态密码显示给用户，该密码有效时间为一个时间步长（通常为 30 秒）。</section>
</li>
</ul>
</li>
</ol>
<h3 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e88eb;">6.2.3 服务端验证动态密码</span></h3>
<ol class="list-paddingleft-1" style="color: #000000;">
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">服务端获取当前时间</strong>：</p>
</section>
<ul class="list-paddingleft-1">
<li>
<section style="color: #010101;">服务端同样获取当前的 Unix 时间戳，并计算对应的时间步长<code style="color: #0e8aeb;">T</code>。</section>
</li>
</ul>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">计算候选动态密码</strong>：</p>
</section>
<ul class="list-paddingleft-1">
<li>
<section style="color: #010101;">服务端使用用户账户绑定的共享密钥<code style="color: #0e8aeb;">K</code> 和当前时间步长<code style="color: #0e8aeb;">T</code>，通过与客户端相同的 TOTP 算法计算动态密码。</section>
</li>
<li>
<section style="color: #010101;">为了容忍客户端和服务端的时间差异，服务端通常会计算当前时间步长<code style="color: #0e8aeb;">T</code> 以及前后几个时间步长（例如<code style="color: #0e8aeb;">T-1</code> 和<code style="color: #0e8aeb;">T+1</code>）的动态密码，形成候选密码列表。</section>
</li>
</ul>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">验证动态密码</strong>：</p>
</section>
<ul class="list-paddingleft-1">
<li>
<section style="color: #010101;">如果匹配成功，则验证通过，用户被允许登录。</section>
</li>
<li>
<section style="color: #010101;">如果所有候选密码都不匹配，则验证失败，拒绝用户登录。</section>
</li>
</ul>
<ul class="list-paddingleft-1">
<li>
<section style="color: #010101;">服务端将用户提交的动态密码与候选密码列表逐一比对：</section>
</li>
</ul>
</li>
</ol>
<h2 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">6.3 关键数据的传递过程</span></h2>
<p style="color: #000000;" data-tool="mdnice编辑器">在整个验证过程中，关键数据的传递和使用如下：</p>
<h3 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e88eb;">6.3.1<strong>初始化阶段</strong></span></h3>
<ul class="list-paddingleft-1" style="color: #000000;">
<li>
<section style="color: #010101;"><strong style="color: #0e88eb;">服务端 → 客户端</strong>：</section>
<ul class="list-paddingleft-1">
<li>
<section style="color: #010101;"><strong style="color: #0e88eb;">共享密钥（K）</strong>：通过二维码或手动输入传递给 Google Authenticator。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #0e88eb;">站点信息</strong>：站点名称、账户名等信息也通过二维码传递。</section>
</li>
</ul>
</li>
</ul>
<h3 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e88eb;">6.3.2<strong>验证阶段</strong></span></h3>
<ul class="list-paddingleft-1" style="color: #000000;">
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">客户端</strong>：</p>
</section>
<ul class="list-paddingleft-1">
<li>
<section style="color: #010101;">本地保存的共享密钥<code style="color: #0e8aeb;">K</code> 和当前时间计算动态密码。</section>
</li>
<li>
<section style="color: #010101;">用户将动态密码（6 位数字）手动输入到登录页面。</section>
</li>
</ul>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">客户端 → 服务端</strong>：</p>
</section>
<ul class="list-paddingleft-1">
<li>
<section style="color: #010101;">用户提交动态密码（6 位数字）和其他常规登录凭据（如用户名、密码）。</section>
</li>
</ul>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">服务端</strong>：</p>
</section>
<ul class="list-paddingleft-1">
<li>
<section style="color: #010101;">使用同样的共享密钥<code style="color: #0e8aeb;">K</code> 和时间步长计算候选动态密码。</section>
</li>
<li>
<section style="color: #010101;">对比用户提交的动态密码与计算结果，完成验证。</section>
</li>
</ul>
</li>
</ul>
<p style="color: #000000;" data-tool="mdnice编辑器">整个过程有如下的一些关键点：</p>
<ol class="list-paddingleft-1" style="color: #000000;">
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">共享密钥的安全性</strong>：</p>
</section>
<ul class="list-paddingleft-1">
<li>
<section style="color: #010101;">共享密钥<code style="color: #0e8aeb;">K</code> 是整个验证过程的核心，必须在初始化阶段通过安全的方式传递，并在客户端和服务端妥善保存。</section>
</li>
<li>
<section style="color: #010101;">密钥不会在验证阶段传输，只有动态密码被提交。</section>
</li>
</ul>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">时间同步</strong>：</p>
</section>
<ul class="list-paddingleft-1">
<li>
<section style="color: #010101;">客户端和服务端的时间必须保持同步，否则计算的时间步长<code style="color: #0e8aeb;">T</code> 会不一致，导致动态密码验证失败。</section>
</li>
<li>
<section style="color: #010101;">为了适应设备的时间漂移，服务端通常允许一定的时间步长偏移（如 ±1 步长）。</section>
</li>
</ul>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">动态密码的短生命周期</strong>：</p>
</section>
<ul class="list-paddingleft-1">
<li>
<section style="color: #010101;">动态密码的有效时间通常为一个时间步长（30 秒），即使密码被窃取，也很快失效。</section>
</li>
</ul>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">离线生成</strong>：</p>
</section>
<ul class="list-paddingleft-1">
<li>
<section style="color: #010101;">动态密码的生成完全依赖共享密钥和时间，无需网络连接，增强了安全性。</section>
</li>
</ul>
</li>
</ol>
<h1 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">7. 小结</span></h1>
<p style="color: #000000;" data-tool="mdnice编辑器">通过 GitHub 强制推行 MFA 的案例，我们可以清晰地看到，MFA 已经成为现代身份管理的重要基石。密码本身的弱点让账户安全长期处于威胁之下，而 MFA 的引入不仅为用户增加了一层甚至多层防护，更在技术上为身份验证树立了一个全新的标准。</p>
<p style="color: #000000;" data-tool="mdnice编辑器">尽管 MFA 并非完美，还存在用户体验、实施成本和一定的攻击风险，但它在密码安全性危机中提供了一种强有力的解决方案。无论是个人用户还是企业，采用 MFA 已经成为抵御网络威胁的必要手段。</p>
<p style="color: #000000;" data-tool="mdnice编辑器">未来，随着技术的进一步发展，多因子认证可能会越来越多地融合生物特征、行为分析和人工智能技术，为用户提供更安全且更便捷的身份验证体验。而对于每一位开发者和用户来说，理解和使用这些技术，不仅是保护自身数字资产的关键，更是应对日益复杂的网络安全形势的必修课。</p>
<p style="color: #000000;" data-tool="mdnice编辑器">以上。</p>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2024/12/architect-must-know-mfa-introduction/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
