首页 > 解决方案 > 如何在使用 java API 并提供正确的凭据时修复 Jenkins 401 Unauthorized

问题描述

我正在尝试使用基于https://wiki.jenkins.io/display/JENKINS/Authenticating+scripted+clients的 Java 连接到 Jenkins

我总是收到 401 Unauthorized 错误。用户名和密码正确,我可以通过浏览器使用它们登录 Jenkins。我也尝试使用令牌代替密码,但它也因同样的错误而失败。

import java.io.IOException;
import java.net.URI;

import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.AuthCache;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.impl.auth.BasicScheme;
import org.apache.http.impl.client.BasicAuthCache;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

public class JenkinsScraper {

    public static void main(String[] args) throws ClientProtocolException, IOException {
        System.out.println(scrape(
                "JenkinUrl",
                "user",
                "token" // "password"
                ));

    }

    public static String scrape(String urlString, String username, String password) throws ClientProtocolException, IOException {
        URI uri = URI.create(urlString);
        HttpHost host = new HttpHost(uri.getHost(), uri.getPort(), uri.getScheme());
        CredentialsProvider credsProvider = new BasicCredentialsProvider();
        credsProvider.setCredentials(new AuthScope(uri.getHost(), uri.getPort()), new UsernamePasswordCredentials(username, password));
        // Create AuthCache instance
        AuthCache authCache = new BasicAuthCache();
        // Generate BASIC scheme object and add it to the local auth cache
        BasicScheme basicAuth = new BasicScheme();
        authCache.put(host, basicAuth);
        CloseableHttpClient httpClient = HttpClients.custom().setDefaultCredentialsProvider(credsProvider).build();
        HttpGet httpGet = new HttpGet(uri);
        // Add AuthCache to the execution context
        HttpClientContext localContext = HttpClientContext.create();
        localContext.setAuthCache(authCache);
        HttpResponse response = httpClient.execute(host, httpGet, localContext);
        System.out.println(response);
        return EntityUtils.toString(response.getEntity());
    }

}

我想了解为什么当凭据正确时我的请求是未经授权的,以及如何解决它。

错误信息

    HttpResponseProxy{HTTP/1.1 401 Unauthorized [Date: Thu, 15 Aug 2019         15:33:31 GMT, Server: Apache/2.4.39 (Win64) mod_authn_ntlm/1.0.8 OpenSSL/1.0.2r, WWW-Authenticate: NTLM, WWW-Authenticate: Basic realm="Private location", Content-Length: 381, Keep-Alive: timeout=5, max=100, Connection: Keep-Alive, Content-Type: text/html; charset=iso-8859-1] ResponseEntityProxy{[Content-Type: text/html; charset=iso-8859-1,Content-Length: 381,Chunked: false]}}
    <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
    <html><head>
    <title>401 Unauthorized</title>
    </head><body>
    <h1>Unauthorized</h1>
    <p>This server could not verify that you
    are authorized to access the document
    requested.  Either you supplied the wrong
    credentials (e.g., bad password), or your
    browser doesn't understand how to supply
    the credentials required.</p>
    </body></html>

标签: javajenkinsjenkins-api

解决方案


以下代码对我来说非常有效:

try
{
    URL url = new URL("http://localhost:8080/job/TestPrj/build"); // Jenkins URL localhost:8080, job named 'test'

    String user = "username"; // username

    String pass = "apitokengeneratedfromjenkins"; // password or API token

    String authStr = user + ":" + pass;

    String encoding = Base64.getEncoder().encodeToString(authStr.getBytes("utf-8"));

    HttpURLConnection connection = (HttpURLConnection)url.openConnection();
    connection.setRequestMethod("POST");
    connection.setDoOutput(true);
    connection.setRequestProperty("Authorization", "Basic " + encoding);
    InputStream content = connection.getInputStream();
    BufferedReader in = new BufferedReader(new InputStreamReader(content));
    String line;
    while ((line = in.readLine()) != null)
    {
        System.out.println(line);
    }
}
catch (Exception e)
{
    e.printStackTrace();
}

推荐阅读