mirror of
https://github.com/mintlify/docs.git
synced 2026-09-14 13:35:46 +08:00
9a4ec7b557
* Fix editor docs accuracy, split media page, clear translation orphans
Accuracy fixes, each verified against mintlify/mint or mintlify/server:
- pages.mdx: "Editors and managers can restore them" -> "admins".
"Manager" is not a Mintlify role.
- index.mdx: publishing on a feature branch does not automatically open a
pull request; you choose commit-to-branch or PR. Contradicted the
branching page's own table.
- branching-and-publishing.mdx: preview deployments build when you open a
pull request, not on every branch save. Confirmed in gitlabWebhooks
(handleMergeRequestOpenEvent) and cruxWebhooks (keyed on reviewId).
tutorial.mdx was already correct.
- settings.mdx: rewritten against editor-settings-form.tsx. The panel has
four sections, not "two layers", and the entire Appearance section was
undocumented - including "Open live preview in new tab", which
live-preview.mdx already linked readers to. Corrected three setting
labels, noted that draft PRs default to on, added the 20,000-character
instruction limit.
- live-preview.mdx: link now resolves to /editor/settings#appearance.
De-bloat:
- Split the media section out of pages.mdx (172 lines, 15 subtopics) into
editor/media.mdx and added it to the nav.
- Trimmed index.mdx from 11 sidebar-duplicating cards to 4.
Translation orphans and redirects:
- Deleted 7 translated files whose English source was removed in April and
June. The translate automation never cleaned them up, and in PR #6062 it
wrote into es|fr|zh/editor/media.mdx 34 days after the English source was
deleted.
- Dropped /editor/media -> /editor/pages so it stops shadowing the
recreated page.
- Added /{es,fr,zh}/editor/publish, completing an English-only redirect.
- Added /editor/collaborate and its language variants. That page was
deleted in June with no redirect and has been a live 404 since.
mint broken-links clean, mint a11y clean, vale 0/0/0 on changed files.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Restructure editor docs: 14 pages to 9, cut UI description
The editor section had grown to 14 pages, about 40% of which described
things a user can see on screen. The ratio was 105 field-enumeration
bullets to 42 procedural steps.
New structure, organized around what is invisible rather than what is
on screen:
Overview absorbs git-essentials (concepts + the Git mapping table)
Tutorial unchanged
Edit content absorbs media and navigation
Publish branch mechanics, conflicts, git sync, commit signing
Review previews, pull requests, approve and merge
Collaborate comments + suggestions + real-time editing
Editor agent trimmed
Settings absorbs configurations as a pointer
Keyboard shortcuts unchanged
Removed: git-essentials, media, navigation, live-preview, comments,
suggestions, configurations, branching-and-publishing. Added: publish,
review, collaborate.
configurations.mdx was the clearest cut. It was a 193-line field-by-field
mirror of the Site configurations panel, which is a third rendering of
information already in the docs.json schema and in organize/settings-*
(2,694 lines). It is now a short section in settings.mdx covering only
what is specific to editing configuration from the editor: real-time
sync, the SVG logo constraint, and the redirects interface.
Also cut: block actions, the minimap, code block options, right-click
menu enumerations, page settings field lists (already delegated to
/organize/pages), and most screenshots of self-evident controls.
1,320 to 848 body lines. Field-enumeration bullets 105 to 29.
English redirects added for all eight removed pages. Language variants
deliberately omitted: es/fr/zh still carry the old structure, so
redirecting those paths now would shadow pages that still exist there.
The translation automation should mirror this restructure; verify
afterward that no orphans remain.
Vale vocabulary widened rather than reworded around: autocommit(s|ed|ing)?,
autosav(e|es|ed|ing), dotfile(s)?.
mint broken-links clean, mint a11y clean, vale 0 errors on editor/.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Correct keyboard shortcuts against the editor keymap
Verified every documented shortcut against the bindings in mintlify/mint
rather than inferring them. The app-level set is exhaustive:
mod+backslash, mod+i, mod+k, mod+s, mod+shift+period, mod+z, shift+mod+d,
shift+mod+s. Visual-mode bindings come from the Tiptap extensions.
- Cmd/Ctrl+Shift+F ("Switch between Navigation and Files tree") does not
exist. No such binding is registered anywhere in the dashboard. Replaced
with the real binding at that spot in the UI: Cmd/Ctrl+Shift+. toggles
"Show all files".
- Added Heading 5 and Heading 6. Heading.configure sets levels 1-6 and
preserves the parent Mod-Alt-N shortcuts; the table stopped at 4.
- Added Cmd/Ctrl+G for accordion group, bound in Accordions.tsx.
Confirmed correct and unchanged: Cmd+K search, Cmd+I agent, Cmd+Shift+S
mode toggle, Cmd+Shift+D diff, Cmd+\ sidebar, Cmd+Shift+M comment,
Cmd+Shift+E suggesting mode, Cmd+Shift+X strikethrough, Cmd+K link,
Cmd+Enter line break, Cmd+Shift+8 unordered list, and that source mode
runs Monaco.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Document auto publish, drop the deprecated deploy branch lock
Auto publish is available to all deployments, so the settings panel shows
"Auto publish" rather than "Main branch autocommits". It is not just a
rename: when it is on, the editor hides the branch selector and the
Publish button entirely (TopBar returns null for both), so there is no
pending state and no review step. Documented that behavior in
settings.mdx and added a note at the top of publish.mdx, since that page
otherwise assumes a publish step exists.
The deployment branch lock was deprecated and removed, so it stays out of
the docs. It was already dropped from settings.mdx in the restructure.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* 💅
* copy edit index
* Fix editor docs I verified against dead code
Three claims traced to code that never mounts. Ethan confirmed the diff
shortcut does not work, which exposed the pattern.
- Removed Cmd/Ctrl+Shift+D for diff view. It is registered only at
SubBar/index.tsx:488, inside EditorSubBar, which is exported and
imported by nothing. There is no live diff shortcut; exitDiff exists
only as an onClick in EditorModeContextMenu.
- Source mode runs CodeMirror, not Monaco. SourceEditor resolves through
source-editor/index.tsx to editor-view.tsx, which imports
@codemirror/state and @codemirror/view. Monaco is used only by
EmbedModal. The shortcut rows themselves were correct: CodeMirror's
defaultKeymap and searchKeymap match VS Code for toggle comment, move
line, duplicate line, find, and add cursor above/below, all confirmed
against @codemirror/commands.
- Rewrote the left panel section of pages.mdx. The tabs are Home and
Publishing (EditorNavigationSidebarContents.tsx:62), not Navigation and
Files. The Navigation/Files switcher lives in the same dead SubBar
component. Home renders the workspace file tree including private
pages; Publishing renders the site navigation and site settings.
Confirmed by the e2e helper openPublishingNavigation, which queries the
Publishing tab by role against the running app.
Also corrected in that section: the tree hides docs.json, dotfiles,
extensionless files, all-caps Markdown, and css/js/jsx/mjs/cjs/pdf unless
Show all files is on; "unlisted" was an invented term, replaced with a
link to /organize/hidden-pages; and the folder menu item is "New page",
confirmed by e2e, not "New file".
Added four source-mode bindings that are real and undocumented: Cmd+B and
Cmd+I insert Markdown markers, Cmd+Option+Shift+[ and ] fold and unfold
all.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* copy edit pages
* copy edit publish
* copy edit review
* copy edit settings
* copy edit collaborate
* Updated mintlify pages
- Updated quickstart.mdx
Mintlify-Source: dashboard-editor
* copy edit keyboard shortcuts
* Updated mintlify pages
- Updated quickstart.mdx
Mintlify-Source: dashboard-editor
* Revert "Updated mintlify pages"
This reverts commit 8d1b50cbfc.
* Updated mintlify pages
- Updated quickstart.mdx
Mintlify-Source: dashboard-editor
* fix editor edits
* Mirror the editor restructure into es, fr, and zh
Brings all three translated sites onto the same nine-page structure as
English instead of waiting for the translate automation, which has a
documented history of leaving orphans behind.
Content:
- Deleted 21 orphans: branching-and-publishing, comments, configurations,
git-essentials, live-preview, navigation, and suggestions in each
language. None had an English source after the restructure.
- Added publish, review, and collaborate in each language.
- Rewrote index, pages, settings, agent, and keyboard-shortcuts to match
the current English content, including Home/Publishing tabs, CodeMirror
source mode, Show all files, and the restored Appearance section.
- Kept the existing conventions: es uses usted, fr uses vous, keywords and
product UI labels stay in English, and every heading is wrapped in a
<div id="english-slug"> so cross-language anchors resolve. Verified that
every English anchor exists in all three languages.
Navigation and redirects:
- es.json, fr.json, and zh.json now list the same nine pages as docs.json.
- Removed six locale redirects that would have shadowed the new publish
and collaborate pages once they existed.
- Added 21 locale redirects for the removed pages and retargeted the
destinations that pointed at them.
- Retargeted four /editor/configurations redirects that pointed at
#site-configurations, an anchor dropped in the settings rewrite.
- Rewrote stale links in changelog, authentication-setup, concepts, and
glossary across all three languages, since broken-links does not follow
redirects.
English fixes needed first, all caused by the settings restructure:
- Restored ## Appearance. Two pages link to #appearance, and its four
preferences were otherwise undocumented.
- Restored ## Create draft pull requests by default, which changelog
links to and which defaults to on.
- Promoted Main branch autocommits from ### to ##; it was nested under PR
instructions, and its warning named a setting no longer on the page.
- Retargeted publish.mdx from the removed #auto-publish anchor.
- Fixed a missing space in the settings page intro.
mint broken-links clean, mint a11y clean (1042 files), vale 0 errors,
all five JSON files valid.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: mintlify[bot] <109931778+mintlify[bot]@users.noreply.github.com>
585 lines
26 KiB
Plaintext
585 lines
26 KiB
Plaintext
---
|
||
title: "认证设置"
|
||
description: "了解如何为 Mintlify 文档站点配置用户认证,使用密码、OAuth、JWT、Info API 或 OAuth 令牌声明控制页面和 API 参考的访问权限,并管理用户登录、公开页面、受保护页面、会话时长以及基于用户组的内容访问。查看不同认证方式的前提条件、配置步骤、用户数据格式和功能可用性。"
|
||
keywords: ['authentication', 'auth', 'OAuth', 'JWT', 'password', 'private']
|
||
---
|
||
|
||
<Info>
|
||
面向你 Mintlify 组织的私有认证适用于所有套餐。
|
||
|
||
密码认证需要 [Pro 或 Enterprise 方案](https://mintlify.com/pricing?ref=authentication)。
|
||
|
||
OAuth 和 JWT 认证需要 [Enterprise 方案](https://mintlify.com/pricing?ref=authentication)。
|
||
</Info>
|
||
|
||
用户必须先登录才能访问你的内容。
|
||
|
||
你可以为所有页面启用完整认证,也可以启用部分认证,将部分页面设为公开、其他页面要求认证。
|
||
|
||
认证仅适用于托管在自定义域名或 Mintlify 子域名上的站点。例如,`docs.example.com` 或 `example.mintlify.site`。使用[自定义子路径](/zh/deploy/docs-subpath)的站点**不支持**认证。例如,`example.com/docs`。
|
||
|
||
若要在保持页面公开的同时识别访客,请使用[个性化](/zh/create/personalization)。个性化支持自定义子路径,并且可以在访客查看页面之前无需完成认证的情况下预填 API 操作台的输入。
|
||
|
||
<div id="choose-an-authentication-method">
|
||
## 选择认证方式
|
||
</div>
|
||
|
||
使用下方对比表来选择适合你使用场景的认证方式。请参见[功能可用性](#feature-availability) 了解每种方式如何与其他 Mintlify 功能协同工作。
|
||
|
||
| 方式 | 适用场景 | 方案 | 基于用户组的访问控制 | API 操作台预填 | 个性化 |
|
||
| :--- | :--- | :--- | :---: | :---: | :---: |
|
||
| Password | 简单的共享访问,无需按用户跟踪 | Pro 或 Enterprise | — | — | — |
|
||
| Private authentication | 面向 Mintlify 组织成员的内部文档 | 所有方案 | — | — | — |
|
||
| OAuth 2.0 | 已有身份提供方或 SSO,且需要按用户会话 | Enterprise | ✓ | ✓ | ✓ |
|
||
| JWT | 自定义认证后端或嵌入在自有登录后的文档 | Enterprise | ✓ | ✓ | ✓ |
|
||
|
||
<div id="configure-authentication">
|
||
## 配置认证
|
||
</div>
|
||
|
||
<Tabs>
|
||
<Tab title="密码">
|
||
<Info>
|
||
密码认证仅提供访问控制,**不**支持用户级功能,例如基于用户组的访问控制或 API 操作台中的预填数据。
|
||
</Info>
|
||
|
||
<div id="password-prerequisites">
|
||
### 密码前提条件
|
||
</div>
|
||
|
||
* 你的安全策略允许在多个用户之间共享密码。
|
||
|
||
<div id="password-setup">
|
||
### 密码设置
|
||
</div>
|
||
|
||
<Steps>
|
||
<Step title="创建密码。">
|
||
1. 在控制台中,前往 [Authentication](https://dashboard.mintlify.com/products/authentication)。
|
||
2. 在 **Authentication method** 部分,将站点可见性设置为 **Private**。
|
||
3. 点击 **Password**。
|
||
4. 输入一个安全的密码。
|
||
5. 点击 **Save changes**。
|
||
|
||
保存后,你的网站会重新部署。部署完成后,任何访问你站点的用户都必须输入该密码才能访问你的内容。
|
||
</Step>
|
||
|
||
<Step title="分发访问权限。">
|
||
以安全方式将密码和文档 URL 分享给获授权的用户。
|
||
</Step>
|
||
</Steps>
|
||
|
||
<div id="password-example">
|
||
### 密码示例
|
||
</div>
|
||
|
||
你将文档托管在 `docs.foo.com`,只需要基础访问控制,而不需要跟踪单个用户。你希望阻止公众访问,同时保持设置简单。
|
||
|
||
在控制台中**创建一个强密码**,并将**凭证分享**给获授权的用户。
|
||
</Tab>
|
||
|
||
<Tab title="私有认证">
|
||
<div id="private-authentication-prerequisites">
|
||
### 私有认证前提条件
|
||
</div>
|
||
|
||
* 所有需要访问你站点的人都必须是你 Mintlify 组织的成员。
|
||
|
||
<div id="private-authentication-setup">
|
||
### 私有认证设置
|
||
</div>
|
||
|
||
<Steps>
|
||
<Step title="启用私有认证。">
|
||
1. 在控制台中,前往 [Authentication](https://dashboard.mintlify.com/products/authentication)。
|
||
2. 在 **Authentication method** 部分,将站点可见性设置为 **Private**。
|
||
3. 点击 **Authenticated**。
|
||
4. 点击 **Save changes**。
|
||
|
||
保存后,你的网站会重新部署。部署完成后,任何访问你网站的人都必须登录到你的 Mintlify 组织才能访问你的内容。
|
||
</Step>
|
||
|
||
<Step title="添加授权用户。">
|
||
1. 在控制台中,前往 [Members](https://dashboard.mintlify.com/settings/organization/members)。
|
||
2. 添加所有需要访问你文档的人员。
|
||
3. 根据他们的编辑权限分配合适的角色。
|
||
</Step>
|
||
</Steps>
|
||
|
||
<div id="private-example">
|
||
### 私有认证示例
|
||
</div>
|
||
|
||
你将文档托管在 `docs.foo.com`,并且整个团队都能访问你的控制台。你希望仅将访问权限限制在团队成员。
|
||
|
||
在控制台设置中**启用私有认证**。
|
||
|
||
通过检查所有团队成员在你的组织中是否为激活状态来**验证团队访问权限**。
|
||
</Tab>
|
||
|
||
<Tab title="OAuth 2.0">
|
||
<div id="oauth-20-prerequisites">
|
||
### OAuth 2.0 前提条件
|
||
</div>
|
||
|
||
* 支持 Authorization Code Flow (授权码流程) 的 OAuth 或 OIDC 服务器。
|
||
* 能够创建可通过 OAuth 访问令牌访问的 API 端点 (可选,用于启用基于用户组的访问控制) 。
|
||
|
||
<div id="oauth-20-setup">
|
||
### OAuth 2.0 设置
|
||
</div>
|
||
|
||
<Steps>
|
||
<Step title="配置你的 OAuth 设置。">
|
||
1. 在控制台中前往 [Authentication](https://dashboard.mintlify.com/products/authentication)。
|
||
2. 在 **Authentication method** 部分,将站点可见性设置为 **Private**。
|
||
3. 点击 **Custom**。
|
||
4. 点击 **OAuth**。
|
||
5. 配置以下字段:
|
||
|
||
* **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 会调用它来获取用户信息。对于基于用户组的访问控制,请使用此字段配置 Info API 方式。你也可以改用 OAuth 令牌声明。如果两者都未配置,OAuth 流程只会验证身份。
|
||
* **Logout URL** (可选) :你的 OAuth 提供方自带的登出 URL。用户登出时,Mintlify 会将登出重定向与该配置的 URL 进行校验,以确保安全性。只有当重定向地址与配置的 `logoutUrl` 完全匹配时,重定向才会成功。如果你未配置登出 URL,用户会被重定向到 `/login`。Mintlify 会使用 `GET` 请求重定向用户,并且不会追加任何 query 参数,因此请将所有参数 (例如 `returnTo`) 直接包含在 URL 中。
|
||
* **Redirect URL** (可选) :在认证完成后重定向用户的 URL。
|
||
|
||
6. 点击 **Save changes**。
|
||
|
||
配置完 OAuth 设置后,你的网站会重新部署。部署完成后,任何访问你站点的用户都必须登录到你的 OAuth 提供方才能访问内容。
|
||
</Step>
|
||
|
||
<Step title="配置你的 OAuth 服务器。">
|
||
1. 从你的[认证设置](https://dashboard.mintlify.com/products/authentication)中复制 **Redirect URL**。
|
||
2. 将该 Redirect URL 添加为 OAuth 服务器中授权的重定向 URL。
|
||
</Step>
|
||
|
||
<Step title="创建用于群组访问的用户信息端点(可选)。">
|
||
如要使用 Info API 方式实现基于用户组的访问控制,请创建一个 API 端点,该端点需满足:
|
||
|
||
* 响应 `GET` 请求。
|
||
* 接受 `Authorization: Bearer <access_token>` 头部用于认证。
|
||
* 以 `User` 格式返回用户数据。更多信息参见 [User data format](#user-data-format)。
|
||
|
||
Mintlify 使用 OAuth 访问令牌调用此端点以获取用户信息。不会发送额外的 query 参数。
|
||
|
||
将此端点 URL 填入你[认证设置](https://dashboard.mintlify.com/products/authentication)中的 **Info API URL** 字段。
|
||
</Step>
|
||
</Steps>
|
||
|
||
<div id="use-groups-from-oauth-token-claims">
|
||
### 使用 OAuth 令牌声明中的用户组
|
||
</div>
|
||
|
||
如果你的身份提供方在 ID 令牌或访问令牌中包含用户组信息,你可以使用这些声明来代替 Info API URL。此选项适用于使用客户端密钥的 OAuth 配置。
|
||
|
||
为部署配置 OAuth 令牌声明时,可以使用以下值:
|
||
|
||
```json
|
||
{
|
||
"source": "id_token",
|
||
"groupsClaim": "groups",
|
||
"groupsDelimiter": ","
|
||
}
|
||
```
|
||
|
||
* `source`:选择 `id_token` 或 `access_token`。如果选择 `id_token`,请在 OAuth scopes 中包含 `openid`。
|
||
* `groupsClaim`:指定包含用户组的令牌声明。默认值为 `groups`。
|
||
* `groupsDelimiter`:可选的分隔符,长度为 1 至 4 个字符。Mintlify 仅使用它来拆分字符串类型的声明值。
|
||
|
||
例如,当 `"groups": "general,clienta_eur"` 且 `groupsDelimiter` 设置为 `","` 时,Mintlify 会将 `general` 和 `clienta_eur` 作为两个独立的用户组。Mintlify 会删除每个用户组两侧的空格,并忽略空片段。
|
||
|
||
不设置 `groupsDelimiter` 时,整个字符串会被视为一个用户组。数组类型的声明始终将每个字符串元素视为一个用户组,不会进行拆分。
|
||
|
||
当分隔符可能出现在用户组名称中时,请不要设置 `groupsDelimiter`。
|
||
|
||
<div id="oauth-20-example">
|
||
### OAuth 2.0 示例
|
||
</div>
|
||
|
||
你将文档托管在 `docs.foo.com`,并且你有一个现有的 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%2Fdocs.foo.com`
|
||
|
||
在 `api.foo.com/docs/user-info` 上**创建一个用户信息端点**,该端点要求使用带有 `provider.users.docs` scope 的 OAuth 访问令牌,并返回:
|
||
|
||
```json
|
||
{
|
||
"groups": ["engineering", "admin"],
|
||
"expiresAt": 1893456000,
|
||
"apiPlaygroundInputs": {
|
||
"header": {
|
||
"Authorization": "Bearer user_abc123"
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
<Note>
|
||
使用用户信息响应中的 `expiresAt` 字段控制会话时长。该字段为 Unix 时间戳 (自纪元以来的秒数) ,用于指示会话何时过期。更多详情请参阅 [用户数据格式](#user-data-format)。
|
||
</Note>
|
||
|
||
**将你的 OAuth 服务器配置为允许重定向**到回调 URL。
|
||
</Tab>
|
||
|
||
<Tab title="JWT(JSON Web Token)">
|
||
<div id="jwt-prerequisites">
|
||
### JWT 前提条件
|
||
</div>
|
||
|
||
* 一个可以生成并签名 JWT 的认证系统。
|
||
* 一个可以创建重定向 URL 的后端服务。
|
||
|
||
<div id="jwt-setup">
|
||
### JWT 设置
|
||
</div>
|
||
|
||
<Steps>
|
||
<Step title="生成私钥。">
|
||
1. 在控制台中前往 [Authentication](https://dashboard.mintlify.com/products/authentication)。
|
||
2. 在 **Authentication method** 部分,将站点可见性设置为 **Private**。
|
||
3. 点击 **Custom**。
|
||
4. 点击 **JWT**。
|
||
5. 输入你现有登录流程的 URL。
|
||
6. 如需提供多个登录流程,点击 **Add login URL** 并为每个选项填写显示名称和 URL。你最多可以配置 10 个登录 URL。
|
||
7. 点击 **Save changes**。
|
||
8. 点击 **Generate new key**。
|
||
9. 将你的 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>
|
||
|
||
当 JWT 认证只配置一个登录 URL 时,未认证的访客会自动重定向到该 URL。如果配置了两个或更多命名的登录 URL,访客会先看到一个选择页面,然后再进入所选的登录流程。Mintlify 会转发经过校验的 `redirect` 参数,使访客能够返回到他们最初请求的文档页面。
|
||
|
||
<Note>
|
||
多个登录 URL 适用于完整或部分 JWT 认证。JWT [个性化](/zh/create/personalization)只接受一个登录 URL,因为它是在不要求访客登录的前提下识别访客,同时继续向其展示公开内容。
|
||
</Note>
|
||
|
||
<div id="jwt-example">
|
||
### JWT 示例
|
||
</div>
|
||
|
||
你在 `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 DOCS_HOST = 'docs.example.com';
|
||
|
||
const signingKey = await jose.importPKCS8(process.env.MINTLIFY_PRIVATE_KEY, 'EdDSA');
|
||
|
||
export async function handleRequest(req: Request, res: Response) {
|
||
const user = {
|
||
host: DOCS_HOST, // 必须与你的文档 URL 匹配
|
||
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_HOST}/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, '')
|
||
DOCS_HOST = 'docs.example.com'
|
||
|
||
@router.get('/auth')
|
||
async def return_mintlify_auth_status(current_user):
|
||
jwt_token = jwt.encode(
|
||
payload={
|
||
'host': DOCS_HOST, # 必须与你的文档 URL 匹配
|
||
'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_HOST}/login/jwt-callback#{jwt_token}', status_code=302)
|
||
```
|
||
</CodeGroup>
|
||
|
||
<div id="redirect-unauthenticated-users">
|
||
### 重定向未认证用户
|
||
</div>
|
||
|
||
当未认证用户尝试访问受保护页面时,系统在重定向到你的登录 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": 1893456000
|
||
}
|
||
```
|
||
|
||
使用 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 = {
|
||
host?: string;
|
||
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>;
|
||
path?: Record<string, unknown>;
|
||
};
|
||
};
|
||
```
|
||
|
||
```json Example
|
||
{
|
||
"host": "docs.example.com",
|
||
"expiresAt": 1893456000,
|
||
"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="host" type="string">
|
||
**JWT 认证时必填。** 你的文档站点的主机名。该字符串必须与你部署文档的 domain 完全一致。Mintlify 会验证 JWT 的 host 是否与发起请求的 host 匹配,以防止令牌在不同站点之间被重复使用。
|
||
</ParamField>
|
||
|
||
<ParamField path="expiresAt" type="number">
|
||
会话过期时间,以自 epoch 起算的秒数表示。当当前时间超过该值时,Mintlify 会让已存储的用户数据过期。访客必须重新完成认证或再次经过识别流程才能刷新该数据。
|
||
|
||
<Warning>**对于 JWT:** 这不同于 JWT 的 `exp` 声明,后者用于决定 JWT 何时被视为无效。出于安全考虑,应将 JWT 的 `exp` 声明设置为较短的时长 (10 秒或更少) 。使用 `expiresAt` 来表示实际会话时长 (从数小时到数周) 。</Warning>
|
||
</ParamField>
|
||
|
||
<ParamField path="groups" type="string[]">
|
||
用户所属用户组的列表。在使用认证时,frontmatter 中带有匹配 `groups` 的页面对该用户可访问。在仅启用个性化(独立于认证)时,用户组只控制页面和内容的可见性,但不会限制通过直接 URL 访问页面。
|
||
|
||
**示例**:具有 `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 操作台中对应的输入字段。用户可以覆盖预填的值,其修改会持久保存在本地存储中。
|
||
|
||
Mintlify 只会应用与当前端点的安全方案匹配的值。
|
||
|
||
<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>
|
||
|
||
<ParamField path="path" type="Record<string, unknown>">
|
||
要预填的路径参数值,以参数名称作为 key。
|
||
</ParamField>
|
||
</Expandable>
|
||
</ParamField>
|
||
|
||
<div id="feature-availability">
|
||
## 功能可用性
|
||
</div>
|
||
|
||
启用认证后,部分功能的行为会有所不同,或可能不可用。
|
||
|
||
| 功能 | 公开 | 完全认证 (所有页面受保护) | 部分认证 (部分页面公开) |
|
||
| :------------------------------------------------------- | :--- | :----------------------------- | :----------------------------- |
|
||
| [llms.txt 和 llms-full.txt](/zh/ai/llmstxt) | 完全支持 | 需要通过认证后才能访问,因此 AI 工具可能无法访问这些文件 | 可公开访问,仅反映公开页面 |
|
||
| [MCP 服务器](/zh/ai/model-context-protocol) | 完全支持 | 连接时需要认证 | 公开页面无需认证即可使用,受保护页面则需要认证 |
|
||
| [Markdown 导出](/zh/ai/markdown-export) | 完全支持 | 完全支持,尊重用户分组 | 完全支持,尊重用户分组 |
|
||
| [PDF 导出](/zh/optimize/pdf-exports) | 完全支持 | 完全支持,尊重用户分组。已认证页面在导出时会包含图片和资源。 | 完全支持,尊重用户分组。已认证页面在导出时会包含图片和资源。 |
|
||
| [搜索](/zh/assistant/index) | 完全支持 | 完全支持,尊重用户分组 | 完全支持,尊重用户分组 |
|
||
| [AI 助手](/zh/assistant/index) | 完全支持 | 完全支持,尊重用户分组 | 完全支持,尊重用户分组 |
|
||
| [skill.md](/zh/ai/skillmd) | 完全支持 | 不支持 | 不支持 |
|
||
| [站点地图](/zh/optimize/seo#sitemaps-and-robotstxt-files) | 完全支持 | 需要通过认证后才能访问,但会排除 groups 中的页面 | 需要通过认证后才能访问,但会排除 groups 中的页面 |
|
||
| [robots.txt](/zh/optimize/seo#sitemaps-and-robotstxt-files) | 完全支持 | 需要通过认证后才能访问 | 需要通过认证后才能访问 |
|
||
| [实时预览](/zh/editor/review#live-preview) | 完全支持 | 支持编辑器自动认证 | 支持编辑器自动认证 |
|