# 多因素认证

EMQX 5.9.0 引入了用于 EMQX Dashboard 的多因素认证（MFA）功能，以增强安全性。此功能要求用户在登录时完成两步认证过程。该过程通过使用密码和基于时间的一次性密码（TOTP）验证用户身份，为系统增加了额外的安全层，防止未经授权的访问。

本页同时从管理员和用户的角度出发解释了如何为 EMQX Dashboard 设置和使用 MFA。

## 关键概念

- **MFA**：一种安全功能，要求提供两种身份验证方式：用户的密码和第二种因素，如由身份验证器应用生成的TOTP。
- **TOTP**：由身份验证应用程序（如 Google Authenticator 或 Authy）生成的临时验证码，基于应用程序与服务器之间共享的密钥。
- **二维码**：共享密钥的图形表示，可以通过身份验证应用程序扫描以简化设置过程。

## MFA 如何工作

当 EMQX Dashboard 启用 MFA 时，它通过增加额外的安全层来增强登录过程。以下是 MFA 的工作原理：

1. **用户登录**：当您尝试登录 Dashboard 时，首先输入您的用户名和密码。
2. **MFA 提示**：如果您的账户启用了 MFA，系统将提示您输入验证码。此验证码由您手机上的身份验证应用程序生成。
3. **首次设置**：如果之前没有设置 MFA，系统将要求您扫描二维码或手动输入密钥，将其添加到您的身份验证应用程序中，完成设置。
4. **后续登录**：完成首次设置后，每次登录时，您需要打开身份验证应用程序并输入它生成的时效性验证码来完成登录过程。

MFA 的目标是确保即使有人获得了您的密码，也无法登录您的账户，因为他们还需要访问您身份验证应用程序中生成的验证码。

::: tip
为增强账户安全性，在为自己或其他用户启用 TOTP 后，请尽快完成初始设置（扫描二维码或手动输入密钥至验证器应用）。若长时间未完成此步骤，且登录密码不慎泄露，可能存在被他人绑定验证器的风险。
:::

## 启用和配置 MFA

MFA 默认为禁用状态。要为用户启用 MFA，管理员必须配置系统以支持 MFA，并为各个用户设置它。只有具有[管理员权限](../dashboard/system.md#用户)的用户才能为其他用户启用或禁用 MFA。

### 默认启用 MFA

要为 Dashboard 所有的用户默认开启 MFA，管理员需要在配置文件中配置 `dashboard.default_mfa` 设置。该设置可以设置为 `none`（禁用 MFA）或 `{mechanism: totp}`（启用基于 TOTP 的 MFA）。

示例配置：

```bash
dashboard.default_mfa = {mechanism: totp}
```

### 通过 EMQX Dashboard 启用 MFA

管理员可以直接通过 Dashboard 启用 MFA，步骤如下：

1. 在 Dashboard 中，点击左侧菜单的**系统设置** -> **用户**。
2. 在**用户**页面中，您将看到一个用户列表。在**操作**列中，点击您要为其启用 MFA 的用户旁边的 **MFA 设置**。
3. 在 **MFA 设置**对话框中，点击**启用 MFA** 以为所选用户启用 MFA。

启用后，用户将在下次登录时需要完成 MFA 设置过程。

::: tip 提示

如果您通过 Dashboard 为自己的账户启用 MFA，系统会在当前会话中立即提示您完成 MFA 设置（参见[首次设置](#首次设置)）。

如果管理员为其他用户启用 MFA，MFA 绑定步骤将延后至该用户下次登录时进行。

:::

### 重置 TOTP 密钥

如果用户需要重置其 TOTP 设置（例如，如果身份验证应用程序被卸载或密钥被泄露），管理员可以通过 **MFA 设置**对话框重置该用户的 TOTP 密钥。

1. 在**系统设置** -> **用户**页面中，找到您要重置 TOTP 密钥的用户。在**操作**列中，点击该用户旁边的 **MFA 设置**。

2. 在 **MFA 设置**对话框中，您将看到**重置 TOTP 密钥**按钮。点击该按钮将启动重置过程。

   会出现一个确认提示，通知您重置密钥将使之前的密钥无效。用户将在下次登录时需要设置一个新的 TOTP 密钥。

3. 点击**确定**以继续重置。重置后，用户将在下次登录时需要遵循首次 MFA 设置过程（扫描新的二维码或将新密钥输入到身份验证应用程序中）。

### 通过配置文件和 REST API 启用和管理 MFA

管理员可以通过配置文件和 REST API 启用或管理用户的 MFA。

::: tip

在 `/users/{username}/mfa` 端点上使用 POST 和 DELETE 方法时，仅管理员或当前身份验证令牌（即 “Bearer token”）的所有者可以使用此接口。也就是说，具有“查看者”角色的用户无法修改其他用户的 MFA 设置。只有与当前身份验证令牌关联的用户（“Bearer token” 拥有者）才能修改自己的 MFA 设置。

有关基于角色的访问控制（RBAC）的更多信息，请参见[用户](../api.md#角色与权限)。

:::

#### 启用特定用户的 MFA

要为特定用户启用 MFA，管理员可以向 `/users/{username}/mfa` API 端点发送 POST 请求，请求体如下：

```json
{
  "mechanism": "totp"
}
```

#### 停用特定用户的 MFA

要为特定用户停用 MFA，管理员可以向 `/users/{username}/mfa` API 端点发送 DELETE 请求。

## 使用 MFA 登录

当 MFA 为您的账户启用后，您需要按照以下步骤登录 EMQX Dashboard：

### 首次设置

在启用 MFA 后的首次登录时，您需要设置身份验证应用程序。

1. **输入您的用户名和密码**： 在登录页面，按通常方式输入您的用户名和密码。

2. **扫描二维码或输入设置密钥**： 在初步验证密码后，Dashboard 将提示您扫描二维码或手动将设置密钥输入到您的身份验证应用程序中以完成设置。

3. **验证应用程序中的代码**： 应用程序将生成未来登录的时效性验证码。输入应用程序中的验证码并点击**确定**。

   该验证码仅在短时间内有效（通常为 30 秒），因此请确保快速输入。

<img src="./assets/mfa_login.png" alt="mfa_login" style="zoom:70%;" />

### 后续登录

完成初次设置后，您可以使用身份验证应用程序登录。

1. **输入您的用户名和密码**： 在后续的登录尝试中，输入您的用户名和密码。
2. **输入 TOTP 代码**： 验证密码后，系统会提示您输入由身份验证应用程序生成的 TOTP 代码。
3. **成功登录**： 如果验证码有效，您将成功登录 Dashboard。
4. **验证码无效**： 如果验证码错误或过期，您将看到一条错误消息。在这种情况下，您可以尝试重新输入当前身份验证应用程序中的验证码。

## 为 SSO 用户强制启用 MFA

除了 Dashboard 的本地账户之外，EMQX 5.10 起还支持为 SSO 用户强制启用 MFA。当您启用了 [单点登录（SSO）](../dashboard/sso.md)（SAML、OIDC 或 LDAP）后，可以针对每个 SSO 后端单独开启该功能，要求所有通过该后端登录的用户在完成 IdP（身份提供方）认证后，额外完成一次 TOTP 双因素验证。

这对部署在公共网络上的 EMQX 尤其重要：即使外部 IdP 的账户不慎泄露，攻击者依然无法登录 Dashboard，除非他们同时掌握用户的 TOTP 验证器。

`force_mfa` 可以针对每个 SSO 后端（`saml`、`oidc` 和 `ldap`）单独配置，不影响本地用户。SSO 用户的 TOTP 密钥与本地用户完全隔离。管理员可以为任意 SSO 用户启用、禁用或重置 MFA；被禁用的用户即便后端开启了 `force_mfa = true` 也会被豁免，适合用于紧急救援账号。

### 为 SSO 后端开启强制 MFA

在 `base.hocon` 中，为每个需要强制 MFA 的后端加上 `force_mfa = true`。也可以在 Dashboard 的 SSO 配置页面中进行配置，详见[配置 LDAP 单点登录](../dashboard/sso-ldap.md)、[配置 SAML 单点登录](../dashboard/sso-saml.md)和[配置 OIDC 单点登录](../dashboard/sso-oidc.md)。

配置示例：

```hocon
dashboard {
  sso {
    saml {
      enable = true
      force_mfa = true          # 所有 SAML 用户登录时必须完成 TOTP
      # ... 其他 SAML 配置
    }
    oidc {
      enable = true
      force_mfa = false         # 不强制；可以在 Dashboard 对单个用户启用
      # ... 其他 OIDC 配置
    }
    ldap {
      enable = true
      force_mfa = true
      # ... 其他 LDAP 配置
    }
  }
}
```

`force_mfa` 默认是 `false`，即升级前的行为，SSO 用户按旧流程登录。

::: tip
开启 `force_mfa` 不会追溯影响已经登录的用户；只会在用户下一次登录时生效。
:::

### 管理单个 SSO 用户的 MFA

在 Dashboard 的**系统设置** -> **用户**页面可以找到所有 SSO 用户（用户名旁会标注所属后端）。点击该用户行的 **MFA 设置**可以：

- **启用 MFA**：让该用户在下次登录时必须绑定并使用 TOTP，即便对应后端的 `force_mfa` 没开。
- **禁用 MFA**：把该用户标记为豁免，即便后端 `force_mfa = true` 也跳过。适用于紧急救援账号。
- **重置 TOTP 密钥**：清除当前密钥，用户下次登录时会重新进入首次设置流程。常用于用户丢失验证器设备时。

### 登录体验

对最终用户而言，强制 MFA 并不会改变 SSO 登录的交互：

1. 正常点击"使用 SSO 登录"按钮；
2. 在 IdP 页面完成身份认证；
3. 回到 Dashboard 后，如果您启用了 MFA，会要求输入一次 TOTP 验证码；
4. 首次登录且该后端已开启 `force_mfa` 时，会先引导您完成 TOTP 绑定（扫码 / 手动添加密钥），再进入 Dashboard。

::: tip 安全说明
登录流程的设计保证了 TOTP 未通过之前**不会**签发任何 Dashboard 访问凭据，即便回调链接被他人截获也无法绕过 MFA。
:::

### 常见问题

**Q：已经登录的 SSO 用户，会因为我开启 `force_mfa` 被踢下线吗？**
A：不会。`force_mfa` 只影响下一次新登录。已有会话继续有效直到过期。

**Q：如何为一个紧急救援账号临时禁用 MFA？**
A：在 Dashboard **用户**页面找到该 SSO 用户，**MFA 设置** -> **禁用 MFA**。该用户后续登录会跳过 TOTP，直到您重新启用或重置。

**Q：能不能只对某一批 SSO 用户启用 MFA，而不是整个后端？**
A：可以。不开启 `force_mfa`（保持 `false`），然后在**用户**页面逐个为需要 MFA 的用户手动启用即可。
