> For the complete documentation index, see [llms.txt](https://gitbook.com/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://gitbook.com/docs/documentation/zh/publish/site-audience/authenticated-access/setting-up-a-custom-backend.md).

# 设置自定义后端

为你的文档访客设置自定义登录界面

{% hint style="warning" %}
本指南将带你完成为你的文档设置受保护登录界面的过程。在阅读本指南之前，请确保你已经先完成了 [启用身份验证访问](/docs/documentation/zh/publish/site-audience/authenticated-access/enabling-authenticated-access.md).
{% endhint %}

本指南将带你使用你自己的 **自定义** 身份验证后端。

{% hint style="info" %}
如果你正在使用我们支持的身份验证提供方之一，或者你有一个 [OpenID Connect](https://auth0.com/docs/authenticate/protocols/openid-connect-protocol) （OIDC）兼容的后端，请查看我们的集成指南，以获得更简化的设置：\
\
[Auth0](/docs/documentation/zh/publish/site-audience/authenticated-access/setting-up-auth0.md) | [Azure AD](/docs/documentation/zh/publish/site-audience/authenticated-access/setting-up-azure-ad.md) | [Okta](/docs/documentation/zh/publish/site-audience/authenticated-access/setting-up-okta.md) | [AWS Cognito](/docs/documentation/zh/publish/site-audience/authenticated-access/setting-up-aws-cognito.md) | [OIDC](/docs/documentation/zh/publish/site-audience/authenticated-access/setting-up-oidc.md)
{% endhint %}

### 概览

要为你的 GitBook 站点设置自定义身份验证系统，请按以下关键步骤操作：

{% stepper %}
{% step %}
[**创建一个自定义后端来对用户进行身份验证**](#id-1.-create-a-custom-backend-to-authenticate-your-users)

实现一个后端，用于提示用户登录并对其进行身份验证。
{% endstep %}

{% step %}
[**签名并将 JWT 令牌传递给 GitBook**](#id-2.-sign-and-pass-a-jwt-token-to-gitbook)

创建一个 JWT 令牌，并使用你站点的私钥对其签名。
{% endstep %}

{% step %}
[**配置登录 URL**](#id-3.-configure-a-login-url)

配置一个在未认证访客访问你的网站时使用的 URL。
{% endstep %}

{% step %}
[**设置多租户身份验证访问（可选）**](#id-4.-set-up-multi-tenant-authenticated-access)

配置你的后端以处理跨多个 GitBook 站点的身份验证。
{% endstep %}

{% step %}
[**为自适应内容配置你的后端（可选）**](#id-5.-configure-your-backend-for-adaptive-content)

配置你的后端以配合 GitBook 中的自适应内容。
{% endstep %}
{% endstepper %}

### 1. 创建一个自定义后端来对用户进行身份验证

为了在用户访问你的文档之前先开始对其进行身份验证，你需要设置一个能够处理用户登录和身份验证的服务器。

你的后端应当：

* 提示用户使用你首选的身份验证方法登录。
* 验证用户凭据并对其进行身份验证。
* 生成并签名一个 **JSON Web 令牌（JWT）** ，在认证成功后。
* 将用户重定向到 GitBook，并在 URL 中包含 JWT。

### 2. 签名并将 JWT 令牌传递给 GitBook

一旦你的后端对用户进行身份验证，它必须 **生成一个 JWT** 和 **将其传递给 GitBook** 当 **重定向** 他们到你的网站。该令牌应使用 **私钥** 在你站点的受众设置中提供的 [启用身份验证访问](/docs/documentation/zh/publish/site-audience/authenticated-access/enabling-authenticated-access.md#enable-authenticated-access).

下面的示例展示了你自定义后端中的登录请求处理程序可能的样子：

{% code title="index.ts" %}

```typescript
import { Request, Response } from 'express';
import * as jose from 'jose';

import { getUserInfo } from '../services/user-info-service';
import { getFeatureFlags } from '../services/feature-flags-service';

const GITBOOK_VISITOR_SIGNING_KEY = process.env.GITBOOK_VISITOR_SIGNING_KEY!;
const GITBOOK_DOCS_URL = 'https://mycompany.gitbook.io/myspace';

export async function handleAppLoginRequest(req: Request, res: Response) {
    // 处理登录请求的业务逻辑
    // 例如，检查凭据并对用户进行身份验证
    //
    // 例如：
    // const loggedInUser = await authenticateUser(req.body.username, req.body.password);
    
    // 生成一个已签名的 JWT
    const gitbookVisitorJWT = await new jose.SignJWT({})
        .setProtectedHeader({ alg: 'HS256' })
        .setIssuedAt()
        .setExpirationTime('2h') // 任意的 2 小时过期时间
        .sign(new TextEncoder().encode(GITBOOK_VISITOR_SIGNING_KEY));
    
    // 将用户重定向到 GitBook，并在 URL 中包含 JWT 令牌
    const redirectURL = `${GITBOOK_DOCS_URL}/?jwt_token=${gitbookVisitorJWT}`;
    res.redirect(redirectURL);
}
```

{% endcode %}

#### 将访客从其 GitBook 会话中登出

要将访客从其 GitBook 会话中登出，请将其重定向到你的网站 URL，并附加 `~gitbook/auth/logout` ：

`https://mycompany.gitbook.io/myspace/~gitbook/auth/logout`

此端点仅会将访客从 GitBook 中登出。如果你还想将其从你自己的身份提供方中登出，请在你自己的登出流程中单独处理。

### 3. 配置登录 URL

当未认证访客尝试访问你的受保护站点时，会使用登录 URL。随后 GitBook 会将他们重定向到此 URL。

此 URL 应指向你自定义后端中的一个处理程序，在那里你可以提示他们登录、进行身份验证，然后将他们重定向回你的网站，并在 URL 中包含 JWT。

例如，如果你的登录页面位于 `https://example.com/login`，你应将此值作为登录 URL。

你可以在站点的受众设置中的“身份验证访问”选项卡下配置此登录 URL。

<figure><img src="https://2111890564-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FNkEGS7hzeqa35sMXQZ4X%2Fuploads%2FB48PEdMz1tCDf0Q0lo4d%2FScreenshot%202025-03-25%20at%2015.00.08.png?alt=media&amp;token=e22fe867-e1f6-44f7-8b4f-a868ac620464" alt="A GitBook screenshot showing where to configure a login URL"><figcaption><p>配置登录 URL</p></figcaption></figure>

#### 使用 GitBook 的登录端点

如果你想在已发布的网站上放置一个登录链接，请链接到 `<publishedSiteURL>/~gitbook/auth/login`.

此端点会将访客重定向到为该站点配置的身份验证后端。它还会添加一个 `location` 与他们开始访问的页面相匹配的查询参数。

这对于页眉链接和其他入口点很有用，你希望在登录后将访客送回同一页面。

在重定向到登录 URL 时，GitBook 会包含一个 `location` 传递给登录 URL 的查询参数，你可以在处理程序中利用它将用户重定向回其原始位置：

```javascript
const gitbookVisitorJWT = await new jose.SignJWT({})
    .setProtectedHeader({ alg: 'HS256' })
    .setIssuedAt()
    .setExpirationTime('2h') // 任意的 2 小时过期时间
    .sign(new TextEncoder().encode(GITBOOK_VISITOR_SIGNING_KEY));
    
// 重定向到原始的 GitBook 文档 URL，并将 JWT 作为 jwt_token 查询参数包含在内
// 如果提供了 location，用户将被重定向回其原始目标位置
const redirectURL = `${GITBOOK_DOCS_URL}/${req.query.location || ''}?jwt_token=${gitbookVisitorJWT}`;
res.redirect(redirectURL);
```

{% hint style="warning" %}
因为 GitBook 依赖于 `location` search 参数——所以你不能在登录 URL 中使用它。例如， `https://auth.gitbook.com/?location=something` 不是一个有效的登录 URL。
{% endhint %}

#### 重定向 MCP 授权请求

当访客连接到 [MCP 服务器](/docs/documentation/zh/ai-for-your-readers/mcp-servers-for-published-docs.md) 你的已发布文档时，GitBook 会将他们重定向到你的身份验证后端。该重定向包含一个 `location` 参数，其中包含 MCP 授权端点的路径，该路径携带一个 `gb_oauth_state` 值，如下所示：

```
~gitbook/oauth2/v1/<site-id>/authorize?gb_oauth_state=<consent_state>
```

你的后端应使用此路径构建最终重定向回 GitBook 站点的 URL。

GitBook 会根据你站点的配置，从以下两个端点之一启动此流程：

* `~gitbook/mcp/auth` 用于启用了自适应内容的部分认证站点。
* `~gitbook/mcp` 用于使用身份验证访问的站点。

一旦你的后端对访客完成身份验证，就通过追加以下内容来构建返回 URL： `location` 将该路径添加到你的 GitBook 站点基础 URL。保留 `gb_oauth_state` 查询参数不变，并添加一个 `jwt_token=<token>` 参数，其中包含你后端生成的已签名 JWT。

你的后端重定向访客所到达的最终 URL 应如下所示：

```
https://<publishedSiteURL>/~gitbook/oauth2/v1/<site-id>/authorize?gb_oauth_state=<consent_state>&jwt_token=<token>
```

#### 使用 GitBook 的登出端点

如果你想在已发布的网站上放置一个登出链接，请链接到 `<publishedSiteURL>/~gitbook/auth/logout`.

此端点会将访客从其 GitBook 会话中登出。

### 4. 设置多租户身份验证访问（可选）

如果你将 GitBook 用作向不同客户提供内容的平台，那么你可能需要设置多租户身份验证访问。你的身份验证后端需要负责处理跨多个不同站点的身份验证。在 GitBook 中，只需对你的自定义身份验证后端代码做一些小调整即可实现。

#### 将所有租户添加到你的身份验证服务器

你的身份验证后端需要知道 JWT 签名密钥以及它需要处理的所有 GitBook 站点的 URL。如果你的组织中有两个站点分别对应 Customer A 和 Customer B，你可以想象你的身份验证代码这样存储映射：

```typescript
const CUSTOMER_A = {
  jwtSigningKey: 'aaa-aaa-aaa-aaa',
  url: 'https://mycompany.gitbook.io/customer-a'
};

const CUSTOMER_B = {
  jwtSigningKey: 'bbb-bbb-bbb-bbb',
  url: 'https://mycompany.gitbook.io/customer-b'
};
```

#### 为你的身份验证服务器提供额外上下文

当 GitBook 无法对用户的请求进行身份验证时，它会将用户重定向到登录 URL。该 URL 指向你的身份验证后端，由它负责对用户进行身份验证并将其重定向回所请求的内容。

为了支持多个租户，你的身份验证后端需要知道用户要访问的是哪个 GitBook 站点。此信息可以通过登录 URL 传递。

例如，你可以按如下方式为每个站点设置登录 URL：

然后你的身份验证后端可以检查此信息，并据此处理重定向到正确的站点：

```javascript
const customerInfo = req.query.site === 'customer-a' ? CUSTOMER_A : CUSTOMER_B;
  
const gitbookVisitorJWT = await new jose.SignJWT({})
    .setProtectedHeader({ alg: 'HS256' })
    .setIssuedAt()
    .setExpirationTime('2h') // 任意的 2 小时过期时间
    .sign(new TextEncoder().encode(customerInfo.jwtSigningKey));
    
// 重定向到原始的 GitBook 文档 URL，并将 JWT 作为 jwt_token 查询参数包含在内
// 如果提供了 location，用户将被重定向回其原始目标位置
const redirectURL = `${customerInfo.url}/${req.query.location || ''}?jwt_token=${gitbookVisitorJWT}`;
res.redirect(redirectURL);
```

### 5. 为自适应内容配置你的后端（可选）

要在身份验证访问设置中利用自适应内容功能，你可以在自定义后端生成的 JWT 负载中包含额外的用户属性（claims），并在将用户重定向到站点时将其包含在 URL 中。

当这些 claims 包含在 JWT 中时，GitBook 会用它们来 [自适应内容](/docs/documentation/zh/publish/adaptive-content/adapting-your-content.md) 为你的站点访客动态调整内容。

将以上内容整合起来，下面的代码示例展示了你如何在 JWT 中包含这些 claims，随后 GitBook 可使用它们为你的访客调整内容：

{% code title="index.ts" %}

```typescript
import { Request, Response } from 'express';
import * as jose from 'jose';

import { getUserInfo } from '../services/user-info-service';
import { getFeatureFlags } from '../services/feature-flags-service';

const GITBOOK_VISITOR_SIGNING_KEY = process.env.GITBOOK_VISITOR_SIGNING_KEY!;
const GITBOOK_DOCS_URL = 'https://mycompany.gitbook.io/myspace';

export async function handleAppLoginRequest(req: Request, res: Response) {
    // 处理登录请求的业务逻辑
    // 例如，检查凭据并对用户进行身份验证
    //
    // 例如：
    // const loggedInUser = await authenticateUser(req.body.username, req.body.password);
    
    // 在本示例中，假设有一个已登录用户对象
    const loggedInUser = { id: '12345' }; // 替换为实际的身份验证逻辑

    // 获取要传递给 GitBook 的用户信息
    const userInfo = await getUserInfo(loggedInUser.id);
    
    // 生成一个已签名的 JWT，并将用户属性作为 claims 包含在内
    const gitbookVisitorClaims = {
        firstName: userInfo.firstName,
        lastName: userInfo.lastName,
        isBetaUser: userInfo.isBetaUser,
        products: userInfo.products.map((product) => product.name),
        featureFlags: await getFeatureFlags({ userId: loggedInUser.id })
    };
    
    const gitbookVisitorJWT = await new jose.SignJWT(gitbookVisitorClaims)
        .setProtectedHeader({ alg: 'HS256' })
        .setIssuedAt()
        .setExpirationTime('2h') // 任意的 2 小时过期时间
        .sign(new TextEncoder().encode(GITBOOK_VISITOR_SIGNING_KEY));
    
    // 将用户重定向到 GitBook，并在 URL 中包含 JWT 令牌
    const redirectURL = `${GITBOOK_DOCS_URL}/?jwt_token=${gitbookVisitorJWT}`;
    res.redirect(redirectURL);
}
```

{% endcode %}

在设置并配置好要发送给 GitBook 的正确 claims 后，前往“[调整你的内容](/docs/documentation/zh/publish/adaptive-content/adapting-your-content.md)”继续配置你的站点。


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://gitbook.com/docs/documentation/zh/publish/site-audience/authenticated-access/setting-up-a-custom-backend.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
