1. 概述

Jenkins 远程访问 API 是自动化 Jenkins 任务的强大工具之一。我们可以使用该 API 来获取构建信息、触发 Jenkins 任务或创建新的 流水线。由于 API 可以访问 Jenkins 的大量功能,因此必须对 API 进行安全保护,防止恶意操作。Jenkins 提供了多种安全机制,其中一种就是要求在请求中包含令牌(token)。

在本教程中,我们将介绍 Jenkins API 的基本使用方式,以及如何通过令牌保护请求。同时也会解释 Jenkins 的 CSRF 保护机制,并说明如何解决 “No Valid Crumb in Request” 错误。

2. 使用 Jenkins API

我们可以使用 HTTP 客户端向 Jenkins API 发送请求。请求必须包含 Jenkins 实例的 IP 地址、API 接口地址以及认证信息。 认证信息包括用户名和一个 API token,或者直接使用密码。推荐始终使用 API token,而不是明文密码。

首先,我们需要为用户生成一个 API token。在 Jenkins 控制台中,点击用户名下的 Security 标签页:

生成 Jenkins API token

Security 区域中,选择 Add new Token

Jenkins 用户安全设置

然后输入 token 名称并点击 Generate

生成 API token

生成后记得将 token 保存下来备用。

接下来我们使用 curl 向 Jenkins 发送请求:

$ curl --user {username}:{apiToken} http://{JENKINS-IP}:{JENKINS-PORT}/api/json?pretty=true

上面命令中使用 --user 选项传入用户名和 API token,然后指定 Jenkins 地址和 API 接口路径。请求返回如下 JSON 格式数据:

---------- OUTPUT TRIMMED ----------------
  "nodeDescription" : "the Jenkins controller's built-in node",
  "nodeName" : "",
  "numExecutors" : 2,
  "description" : null,
  "jobs" : [
    {
      "_class" : "hudson.model.FreeStyleProject",
      "name" : "sample-job",
      "url" : "https://8085-port-e7xgmenbzvw4pkcu./job/sample-job/",
      "color" : "blue"
    }

从输出中可以看到 Jenkins 实例的基本信息、执行器数量以及当前任务列表。

3. Jenkins 的 CSRF 保护机制

CSRF 是一种常见的 Web 安全攻击,攻击者通过伪造用户身份向 Web 应用发送恶意请求。为了防止这类攻击,Jenkins 默认启用了 CSRF 保护机制,要求 API 请求中必须包含额外的令牌(crumb token)。

当使用明文密码进行 API 认证时,Jenkins 会要求提供 crumb token。

我们可以在 Jenkins 的安全设置中查看 CSRF 配置:

Jenkins 安全配置

可以看到 CSRF protection 部分和当前使用的 crumb token 提供者:

Jenkins CSRF 保护配置

说明当前 Jenkins 已启用 CSRF 保护。

我们尝试使用密码直接触发一个任务:

$ curl -X POST --user {username}:{password} http://{JENKINS-IP}:{JENKINS-PORT}/job/sample-job/build

返回如下错误:

<title>Error 403 No valid crumb was included in the request</title>
</head>
<body><h2>HTTP ERROR 403 No valid crumb was included in the request</h2>
<table>
<tr><th>URI:</th><td>/job/sample-job/build</td></tr>
<tr><th>STATUS:</th><td>403</td></tr>
<tr><th>MESSAGE:</th><td>No valid crumb was included in the request</td></tr>
<tr><th>SERVLET:</th><td>Stapler</td></tr>
</table>

说明请求中缺少有效的 crumb token,导致被 Jenkins 拒绝。✅

4. 解决 “No Valid Crumb” 问题

针对这个问题,我们有多种解决方案,具体取决于我们的使用场景。

4.1. 为用户生成 Crumb Token

我们可以通过访问 Jenkins 的 /crumbIssuer/api/ 接口来生成 crumb token。生成后,将该 token 作为 Jenkins-Crumb 请求头添加到原始请求中即可。

示例:

$ curl http://{JENKINS-IP}:{JENKINS-PORT}/crumbIssuer/api/json?pretty=true --user {username}:{password}
{
  "_class" : "hudson.security.csrf.DefaultCrumbIssuer",
  "crumb" : "8454e33c1ce5482a0ea4603a5379a12a9c31eafd65696685c93be5e463db55f8",
  "crumbRequestField" : "Jenkins-Crumb"
}

拿到 crumb 字段值后,将其作为请求头再次触发任务:

$ curl -X POST http://{JENKINS-IP}:{JENKINS-PORT}/job/sample-job/build --user {username}:{password} -H "Jenkins-Crumb: 8454e33c1ce5482a0ea4603a5379a12a9c31eafd65696685c93be5e463db55f8"

任务成功触发:

使用 crumb token 触发构建

4.2. 使用 API Token 替代密码

正如前面所说,只有使用密码进行认证时才需要 crumb token。如果我们没有强制要求使用密码,可以使用 API token 进行认证,这样就无需提供 crumb token:

$ curl -X POST http://{JENKINS-IP}:{JENKINS-PORT}/job/sample-job/build --user {username}:{apiToken}

任务同样成功触发:

使用 API token 触发构建

5. 总结

在本文中,我们讲解了如何解决向 Jenkins 发送 API 请求时遇到的 “No valid crumb” 错误。我们介绍了 Jenkins 的 CSRF 保护机制,并演示了两种解决方案:

  • ✅ 获取并使用 crumb token 发送请求(适用于使用密码认证的场景)
  • ✅ 使用 API token 替代密码(避免使用 crumb token)

对于自动化脚本来说,推荐使用 API token,不仅更安全,而且避免了处理 crumb token 的复杂性。如果你在 CI/CD 流水线中遇到该错误,可以优先考虑使用 API token 方式进行认证。


原始标题:Troubleshooting Jenkins 403 No Valid Crumb in Request Error