Files
mintlify__docs/zh/deploy/authentication-setup.mdx
locadex-agent[bot] 886aa0b3a2 docs(locadex): add translations (#3028)
Co-authored-by: locadex-agent[bot] <217277504+locadex-agent[bot]@users.noreply.github.com>
2026-02-02 08:29:44 -08:00

470 lines
18 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: "认证设置"
description: "通过用户认证来控制对文档的访问。"
keywords: ['authentication', 'auth', 'OAuth', 'JWT', 'password']
---
<Info>
[Pro 方案](https://mintlify.com/pricing?ref=authentication) 包含密码认证。
[Enterprise 方案](https://mintlify.com/pricing?ref=authentication) 包含所有认证方式。
</Info>
启用认证后,用户需先登录才能访问你的文档。
启用认证后,用户必须先登录才能访问任何内容。你可以将特定页面或分组配置为公开,而将其他页面设为受保护状态。
<div id="configure-authentication">
## 配置认证
</div>
选择要配置的握手方式。
<Tabs>
<Tab title="密码">
<Info>
密码认证仅提供访问控制,**不**支持用户级功能,例如基于用户组的访问控制或 API 操作台中的预填数据。
</Info>
### 前提条件
* 你的安全策略允许在多个用户之间共享密码。
### 设置
<Steps>
<Step title="创建密码。">
1. 在控制台中,前往 [Authentication](https://dashboard.mintlify.com/settings/deployment/authentication)。
2. 启用认证。
3. 在 **Password Protection** 部分输入一个安全的密码。
输入密码后,你的网站会重新部署。部署完成后,任何访问你站点的用户都必须输入该密码才能访问你的内容。
</Step>
<Step title="分发访问权限。">
以安全方式将密码和文档 URL 分享给获授权的用户。
</Step>
</Steps>
### 示例
你将文档托管在 `docs.foo.com`,只需要基础访问控制,而不需要跟踪单个用户。你希望阻止公众访问,同时保持设置简单。
在控制台中**创建一个强密码**,并将**凭证分享**给获授权的用户。就这么简单!
</Tab>
<Tab title="Mintlify 控制台">
### 前提条件
* 所有需要访问你文档的人都必须是你 Mintlify 组织的成员。
### 设置
<Steps>
<Step title="在 Mintlify 控制台中启用认证。">
1. 在控制台中,前往 [Authentication](https://dashboard.mintlify.com/settings/deployment/authentication)。
2. 启用认证。
3. 在 **Custom Authentication** 部分,点击 **Mintlify Auth**。
4. 点击 **Enable Mintlify Auth**。
启用 Mintlify 认证后,你的网站会重新部署。部署完成后,任何访问你网站的人都必须登录到你的 Mintlify 组织才能访问你的内容。
</Step>
<Step title="添加授权用户。">
1. 在控制台中,前往 [Members](https://dashboard.mintlify.com/settings/organization/members)。
2. 添加所有需要访问你文档的人员。
3. 根据他们的编辑权限分配合适的角色。
</Step>
</Steps>
### 示例
你将文档托管在 `docs.foo.com`,并且整个团队都能访问你的控制台。你希望仅将访问权限限制在团队成员。
在控制台设置中**启用 Mintlify 认证**。
通过检查所有团队成员在你的组织中是否为激活状态来**验证团队访问权限**。
</Tab>
<Tab title="OAuth 2.0">
### 前提条件
* 支持 Authorization Code Flow(授权码流程)的 OAuth 或 OIDC 服务器。
* 能够创建可通过 OAuth 访问令牌访问的 API 端点(可选,用于启用基于用户组的访问控制)。
### 设置
<Steps>
<Step title="配置你的 OAuth 设置。">
1. 在控制台中前往 [Authentication](https://dashboard.mintlify.com/settings/deployment/authentication)。
2. 启用认证。
3. 在 **Custom Authentication** 部分,点击 **OAuth**。
4. 配置以下字段:
* **Authorization URL**:你的 OAuth 端点。
* **Client ID**:你的 OAuth 2.0 客户端标识符。
* **Client Secret**:你的 OAuth 2.0 客户端密钥。
* **Scopes**(可选):要请求的权限。复制 **完整的** scope 字符串(例如,对于 `provider.users.docs` 这样的 scope,复制完整的 `provider.users.docs`)。如果需要不同的访问级别,可以使用多个 scope。
* **Additional authorization parameters**(可选):要添加到初始授权请求中的其他 query 参数。
* **Token URL**:你的 OAuth 令牌交换端点。
* **Info API URL**(可选):你服务器上的一个端点,Mintlify 会调用它来获取用户信息。对于基于用户组的访问控制是必填项。如果省略,OAuth 流程只会验证身份。
* **Logout URL**(可选):你的 OAuth 提供方自带的登出 URL。用户登出时,Mintlify 会将登出重定向与该配置的 URL 进行校验,以确保安全性。只有当重定向地址与配置的 `logoutUrl` 完全匹配时,重定向才会成功。如果你未配置登出 URL,用户会被重定向到 `/login`。Mintlify 会使用 `GET` 请求重定向用户,并且不会追加任何 query 参数,因此请将所有参数(例如 `returnTo`)直接包含在 URL 中。
* **Redirect URL**(可选):在认证完成后重定向用户的 URL。
5. 点击 **保存更改**。
配置完 OAuth 设置后,你的网站会重新部署。部署完成后,任何访问你站点的用户都必须登录到你的 OAuth 提供方才能访问内容。
</Step>
<Step title="配置你的 OAuth 服务器。">
1. 从你的[认证设置](https://dashboard.mintlify.com/settings/deployment/authentication)中复制 **Redirect URL**。
2. 将该 Redirect URL 添加为 OAuth 服务器中授权的重定向 URL。
</Step>
<Step title="创建用户信息端点(可选)。">
为启用基于用户组的访问控制,创建一个 API 端点,该端点需满足:
* 响应 `GET` 请求。
* 接受 `Authorization: Bearer <access_token>` 头部用于认证。
* 以 `User` 格式返回用户数据。更多信息参见 [User data format](#user-data-format)。
Mintlify 使用 OAuth 访问令牌调用此端点以获取用户信息。不会发送额外的 query 参数。
将此端点 URL 填入你[认证设置](https://dashboard.mintlify.com/settings/deployment/authentication)中的 **Info API URL** 字段。
</Step>
</Steps>
### 示例
你将文档托管在 `foo.com/docs`,并且你有一个现有的 OAuth 服务器 `auth.foo.com`,它支持 Authorization Code Flow。
在控制台中**配置你的 OAuth 服务器详细信息**:
* **Authorization URL**:`https://auth.foo.com/authorization`
* **Client ID**:`ydybo4SD8PR73vzWWd6S0ObH`
* **Scopes**:`['provider.users.docs']`
* **Token URL**:`https://auth.foo.com/exchange`
* **Info API URL**:`https://api.foo.com/docs/user-info`
* **Logout URL**:`https://auth.foo.com/logout?returnTo=https%3A%2F%2Ffoo.com%2Fdocs`
在 `api.foo.com/docs/user-info` 上**创建一个用户信息端点**,该端点要求使用带有 `provider.users.docs` scope 的 OAuth 访问令牌,并返回:
```json
{
"groups": ["engineering", "admin"],
"expiresAt": 1735689600,
"apiPlaygroundInputs": {
"header": {
"Authorization": "Bearer user_abc123"
}
}
}
```
<Note>
使用用户信息响应中的 `expiresAt` 字段控制会话时长。该字段为 Unix 时间戳(自纪元以来的秒数),用于指示会话何时过期。更多详情请参阅 [用户数据格式](#user-data-format)。
</Note>
**将你的 OAuth 服务器配置为允许重定向**到回调 URL。
</Tab>
<Tab title="JWT(JSON Web Token)">
### 前提条件
* 一个可以生成并签名 JWT 的认证系统。
* 一个可以创建重定向 URL 的后端服务。
### 设置
<Steps>
<Step title="生成私钥。">
1. 在控制台中前往 [Authentication](https://dashboard.mintlify.com/settings/deployment/authentication)。
2. 启用认证。
3. 在 **Custom Authentication** 部分,点击 **JWT**。
4. 输入你现有登录流程的 URL。
5. 点击 **Save changes(保存更改)**。
6. 点击 **Generate new key(生成新密钥)**。
7. 将你的 key 安全存储在后端可以访问的位置。
生成私钥后,你的网站会重新部署。部署完成后,任何访问你网站的人都必须登录到你的 JWT 认证系统才能访问你的内容。
</Step>
<Step title="将 Mintlify 认证集成到你的登录流程中。">
修改你现有的登录流程,在用户通过认证后增加以下步骤:
* 按 `User` 格式创建一个包含已认证用户信息的 JWT。更多信息参见 [User data format](#user-data-format)。
* 使用 EdDSA 算法,用你的密钥对 JWT 进行签名。
* 创建一个返回到文档 `/login/jwt-callback` 路径的重定向 URL,并将 JWT 放在 URL 片段(hash)中。
</Step>
</Steps>
### 示例
你在 `docs.foo.com` 上托管文档,并在 `foo.com` 上已有认证系统。你希望扩展登录流程,在保持文档与控制台分离的同时,为文档授予访问权限(或者如果你没有控制台,则直接为文档授予访问权限)。
在 `https://foo.com/docs-login` 创建一个登录端点,用于扩展你现有的认证逻辑。
在验证用户凭据之后:
* 按 Mintlify 的格式生成包含用户数据的 JWT。
* 对 JWT 进行签名并重定向到 `https://docs.foo.com/login/jwt-callback#{SIGNED_JWT}`。
<CodeGroup>
```ts TypeScript
import * as jose from 'jose';
import { Request, Response } from 'express';
const TWO_WEEKS_IN_MS = 1000 * 60 * 60 * 24 * 7 * 2;
const signingKey = await jose.importPKCS8(process.env.MINTLIFY_PRIVATE_KEY, 'EdDSA');
export async function handleRequest(req: Request, res: Response) {
const user = {
expiresAt: Math.floor((Date.now() + TWO_WEEKS_IN_MS) / 1000), // 2 周会话过期时间
groups: res.locals.user.groups,
apiPlaygroundInputs: {
header: {
"Authorization": `Bearer ${res.locals.user.apiKey}`,
},
},
};
const jwt = await new jose.SignJWT(user)
.setProtectedHeader({ alg: 'EdDSA' })
.setExpirationTime('10 s') // JWT 10 秒后过期
.sign(signingKey);
return res.redirect(`https://docs.foo.com/login/jwt-callback#${jwt}`);
}
```
```python Python
import jwt # pyjwt
import os
from datetime import datetime, timedelta
from fastapi.responses import RedirectResponse
private_key = os.getenv(MINTLIFY_JWT_PEM_SECRET_NAME, '')
@router.get('/auth')
async def return_mintlify_auth_status(current_user):
jwt_token = jwt.encode(
payload={
'exp': int((datetime.now() + timedelta(seconds=10)).timestamp()), # JWT 10 秒后过期
'expiresAt': int((datetime.now() + timedelta(weeks=2)).timestamp()), # 2 周会话过期时间
'groups': ['admin'] if current_user.is_admin else [],
'apiPlaygroundInputs': {
'header': {
'Authorization': f'Bearer {current_user.api_key}',
},
},
},
key=private_key,
algorithm='EdDSA'
)
return RedirectResponse(url=f'https://docs.foo.com/login/jwt-callback#{jwt_token}', status_code=302)
```
</CodeGroup>
### 重定向未认证用户
当未认证用户尝试访问受保护页面时,系统在重定向到你的登录 URL 时会保留用户的目标地址。
1. 用户尝试访问受保护页面:`https://docs.foo.com/quickstart`。
2. 重定向到带有 redirect 查询参数的登录 URL:`https://foo.com/docs-login?redirect=%2Fquickstart`。
3. 认证完成后,重定向到 `https://docs.foo.com/login/jwt-callback?redirect=%2Fquickstart#{SIGNED_JWT}`。
4. 用户将进入其最初想要访问的页面。
</Tab>
</Tabs>
<div id="make-pages-public">
## 公开页面
</div>
在使用认证时,所有页面默认都需要通过认证才能访问。你可以在页面或分组级别通过 `public` 属性将特定页面设置为无需认证即可访问。
<div id="individual-pages">
### 单个页面
</div>
要将页面设为公开,请在该页面的 frontmatter 中添加 `public: true`。
```mdx Public page example
---
title: "公开页面"
public: true
---
```
<div id="groups-of-pages">
### 页面分组
</div>
要将某个分组中的所有页面设为公开,请在 `docs.json` 的 `navigation` 对象中,该分组名称下添加 `"public": true`。
```json Public group example
{
"navigation": {
"groups": [
{
"group": "公开组",
"public": true,
"icon": "play",
"pages": [
"quickstart",
"installation",
"settings"
]
},
{
"group": "私有组",
"icon": "pause",
"pages": [
"private-information",
"secret-settings"
]
}
]
}
}
```
<div id="control-access-with-groups">
## 使用 groups 控制访问
</div>
当你使用 OAuth 或 JWT(JSON Web Token)进行认证时,可以将特定页面仅限于某些用户组访问。若希望不同用户根据其角色或属性查看不同内容,这将非常有用。
通过在认证过程中传递的用户数据来管理 groups。详见 [用户数据格式](#user-data-format)。
```json Example user info
{
"groups": ["admin", "beta-users"],
"expiresAt": 1735689600
}
```
使用 frontmatter 中的 `groups` 属性来指定哪些 groups 可以访问特定页面。
```mdx Example page restricted to the admin group highlight={3}
---
title: "管理员控制台"
groups: ["admin"]
---
```
用户必须至少属于所列的一个 groups 才能访问该页面。如果用户在不具备所需分组的情况下尝试访问页面,将会收到 404 错误。
<div id="how-groups-interact-with-public-pages">
### groups 如何与公共页面配合使用
</div>
* 默认情况下,所有页面都需要认证。
* 具有 `groups` 属性的页面仅对属于这些 groups 的已认证用户可访问。
* 没有 `groups` 属性的页面对所有已认证用户可访问。
* 具有 `public: true` 且没有 `groups` 属性的页面对所有人可访问。
<CodeGroup>
```mdx Public page
---
title: "Public guide"
public: true
---
```
```mdx Protected page
---
title: "API reference"
---
```
```mdx Protected page with groups
---
title: "Advanced configurations"
groups: ["pro", "enterprise"]
---
```
</CodeGroup>
<div id="user-data-format">
## 用户数据格式
</div>
当使用 OAuth 或 JWT 认证时,系统会返回用户数据,用于控制会话时长、基于用户组成员关系的访问控制,以及[内容个性化](/zh/create/personalization)。
<CodeGroup>
```tsx Format
type User = {
expiresAt?: number;
groups?: string[];
content?: Record<string, any>;
apiPlaygroundInputs?: {
server?: Record<string, string>;
header?: Record<string, unknown>;
query?: Record<string, unknown>;
cookie?: Record<string, unknown>;
};
};
```
```json Example
{
"expiresAt": 1735689600,
"groups": ["admin", "beta-users"],
"content": {
"firstName": "Jane",
"company": "Acme Corp"
},
"apiPlaygroundInputs": {
"header": {
"Authorization": "Bearer user_abc123"
},
"server": {
"baseUrl": "https://api.foo.com"
}
}
}
```
</CodeGroup>
<ParamField path="expiresAt" type="number">
会话过期时间,以自 epoch 起算的秒数表示。当当前时间超过该值时,用户必须重新完成认证。
<Warning>**对于 JWT:** 这不同于 JWT 的 `exp` 声明,后者用于决定 JWT 何时被视为无效。出于安全考虑,应将 JWT 的 `exp` 声明设置为较短的时长(10 秒或更少)。使用 `expiresAt` 来表示实际会话时长(从数小时到数周)。</Warning>
</ParamField>
<ParamField path="groups" type="string[]">
用户所属用户组的列表。frontmatter 中带有匹配 `groups` 的页面对该用户可访问。
**示例**:具有 `groups: ["admin", "engineering"]` 的用户可以访问带有 `admin` 或 `engineering` 用户组标记的页面。
</ParamField>
<ParamField path="content" type="Record<string, any>">
可在 MDX 页面中通过 `user` 变量访问的自定义数据,用于[个性化内容](/zh/create/personalization#dynamic-mdx-content)。
</ParamField>
<ParamField path="apiPlaygroundInputs" type="object">
使用用户特定的值预填 API 操作台中的字段。当用户完成认证后,这些值会填充到 API 操作台中对应的输入字段。用户可以覆盖预填的值,其修改会持久保存在本地存储中。
只有与当前端点的安全方案匹配的值才会被应用。
<Expandable title="properties">
<ParamField path="header" type="Record<string, unknown>">
要预填的 Header 值,以 Header 名称作为 key。
</ParamField>
<ParamField path="query" type="Record<string, unknown>">
要预填的查询参数值,以参数名称作为 key。
</ParamField>
<ParamField path="cookie" type="Record<string, unknown>">
要预填的 Cookie 值,以 Cookie 名称作为 key。
</ParamField>
<ParamField path="server" type="Record<string, string>">
要预填的服务器变量值,以变量名称作为 key。
</ParamField>
</Expandable>
</ParamField>