如何以 HTML 形式正确使用 Jenkins crumbs

How to properly use Jenkins crumbs in an HTML form

我正在开发一个 Jenkins 插件,该插件在使用 Jelly 和 Stapler 请求生成的页面上使用 HTML 表单。升级到较新版本的 Jenkins 后,此表单中的 POSTs 停止工作,Jenkins 出现以下 403 错误:

HTTP ERROR 403 No valid crumb was included in the request
URI:    /job/Watchr_Sandbox/performanceReports/
STATUS: 403
MESSAGE:    No valid crumb was included in the request
SERVLET:    Stapler

我对最近的CSRF security improvement to Jenkins that seems to be at the root of this problem, and I've read a lot of other Stack Overflow solutions to this problem (this one seems to be closest)做了很多研究,但我没有找到任何与我的情况完全一样的例子。

基本上,我希望表单的 POST 包含 Jenkins 面包屑信息。现在,我正试图通过将面包屑信息作为隐藏的表单值来解决这个问题,但我不知道我是否以正确的方式获取 Jenkins 面包屑,或者我是否正确地解决了这个问题。

.果冻文件

<j:jelly xmlns:j="jelly:core" xmlns:g="glide" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:test="/lib/hudson/test" xmlns:f="/lib/form" xmlns:i="jelly:fmt" xmlns:RP="jelly:RP">
  
  <l:layout title="Performance Reports">
    <st:include page="sidepanel.jelly" it="${it.getOwner()}" />
    <l:main-panel>
        <j:out value="${it.createHtml()}"/>
    </l:main-panel>

  </l:layout>
</j:jelly>

Java代码

import org.kohsuke.stapler.CrumbIssuer;
import org.kohsuke.stapler.Stapler;
import hudson.Functions;

public String createHtml() {
    StringBuilder sb = new StringBuilder();
    String crumb = Functions.getCrumb(Stapler.getCurrentRequest());
    String crumbRequestField = Functions.getCrumbRequestField();

    sb.append("<form method=\"post\" autocomplete=\"off\"");

    // ...

    sb.append("<input type=\"hidden\"");
    sb.append(" id=\"crumb\"");
    sb.append(" name=\"crumb\"");
    sb.append(" value=\"").append(crumb).append("\"");
    sb.append("/>");
   
    sb.append("<input type=\"hidden\"");
    sb.append(" id=\"crumbRequestField\"");
    sb.append(" name=\"crumbRequestField\"");
    sb.append(" value=\"").append(crumbRequestField).append("\"");
    sb.append("/>");

    // ...

    sb.append("</form>");

    return sb.toString();
}

终于找到了答案,多亏了另一个问题:

The problem was that for some reason, the name of the crumb header appended to the requests by default is actually wrong. It's Crumb as shown in the screenshot in my question, but it actually should be Jenkins-Crumb or .crumb for older versions of Jenkins.

所以在我的例子中,我只需要更改代码以使用“Jenkins-Crumb”而不是“crumb”,它完美地工作:

    sb.append("<input type=\"hidden\"");
    sb.append(" id=\"Jenkins-Crumb\"");
    sb.append(" name=\"Jenkins-Crumb\"");
    sb.append(" value=\"").append(crumb).append("\"");
    sb.append("/>");