At the first access to the server, my authorization is successful (although this is not correct). I don’t understand why digest authorization in this code occurs so early.
I'm using the following solution:
import java.io.Serializable;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.*;
import java.util.stream.Collectors;
import org.apache.commons.io.IOUtils;
import org.apache.http.*;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.*;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.conn.ssl.AllowAllHostnameVerifier;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.impl.auth.DigestScheme;
import org.apache.http.impl.client.*;
import org.apache.http.ssl.SSLContextBuilder;
import org.testng.Assert;
import javax.net.ssl.*;
public class SOAPClientApache {
private static final String URL = "https://httpbin.org/digest-auth/auth/user/passwd";
private static final String PASSWORD = "passwd"; //passwd
private static final String USER = "user"; //user
public void run() throws Exception {
HttpGet httpget = new HttpGet(URL);
HttpHost target = new HttpHost(httpget.getURI().getHost(), 443, "https");
CredentialsProvider credsProvider = new BasicCredentialsProvider();
UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(USER, PASSWORD);
credsProvider.setCredentials(
new AuthScope(target.getHostName(), target.getPort()),
credentials);
CookieStore cookieStore = new BasicCookieStore();
//SSL solution
CloseableHttpClient httpclient
= HttpClients.custom().setDefaultCookieStore(cookieStore)
.setDefaultCredentialsProvider(credsProvider).build();
try {
DigestScheme digestAuth = new DigestScheme();
digestAuth.overrideParamter("qop", "auth");
digestAuth.overrideParamter("nc", "0");
digestAuth.overrideParamter("cnonce", DigestScheme.createCnonce());
AuthCache authCache = new BasicAuthCache();
authCache.put(target, digestAuth);
HttpClientContext localContext = HttpClientContext.create();
localContext.setAuthCache(authCache);
CloseableHttpResponse response;
response = httpclient.execute(target, httpget, localContext);
//Массив headers (для тестов)
Header[] headers = response.getAllHeaders();
for (Header header : headers) {
System.out.println(header);
}
System.out.println();
Map<String, String> wwwAuth = Arrays
.stream(response.getHeaders("WWW-Authenticate")[0]
.getElements())
.collect(Collectors.toMap(HeaderElement::getName,
HeaderElement::getValue));
//Выведем наш массивчик чтобы лицезреть
for(Map.Entry<String, String> pair : wwwAuth.entrySet()){
System.out.println(pair.getKey() + " = " + pair.getValue());
}
// the first call ALWAYS fails with a 401
Assert.assertEquals(response.getStatusLine().getStatusCode(), 401);
digestAuth.overrideParamter("opaque", wwwAuth.get("opaque"));
digestAuth.overrideParamter("nonce", wwwAuth.get("nonce"));
digestAuth.overrideParamter("realm", wwwAuth.get("Digest realm"));
Header authenticate = digestAuth.authenticate(credentials, httpget, localContext);
httpget.addHeader(authenticate);
response = httpclient.execute(target, httpget, localContext);
// the 2nd call is the real deal
Assert.assertEquals(response.getStatusLine().getStatusCode(), 200);
System.out.println(IOUtils
.toString(response.getEntity().getContent(), "utf-8"));
} finally {
httpclient.close();
}
}
}
When the program reaches this step:
Map<String, String> wwwAuth = Arrays
.stream(response.getHeaders("WWW-Authenticate")[0]
.getElements())
.collect(Collectors.toMap(HeaderElement::getName,
HeaderElement::getValue));
then "response: HTTP / 1.1 200 OK" and the program exits to exception
Related
I am trying to make a SOAP activity with digest authorization. When i am trying to connect to the test service, I get the below error:
Exception in thread "main" org.apache.http.conn.HttpHostConnectException: Connect to httpbin.org:135 [httpbin.org/34.231.30.52, httpbin.org/54.166.163.67, httpbin.org/54.91.118.50, httpbin.org/34.199.75.4] failed: Connection timed out: connect
at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:159)
at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:359)
at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:381)
at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:237)
at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:185)
at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89)
at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:111)
at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:72)
at SOAPClientApache.run(SOAPClientApache.java:94)
at Main.main(Main.java:4)
Caused by: java.net.ConnectException: Connection timed out: connect
at java.base/java.net.PlainSocketImpl.connect0(Native Method)
at java.base/java.net.PlainSocketImpl.socketConnect(PlainSocketImpl.java:101)
at java.base/java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:399)
at java.base/java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:242)
at java.base/java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:224)
at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.base/java.net.Socket.connect(Socket.java:609)
at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:339)
at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:142)
... 10 more
What I did for the solution:
Changed the port number
Changed the URL
Changed the PC on which the project was launched...Nothing helped me :(
I would be grateful for any help. Code:
SOAPClientApache
import java.io.Serializable;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Map;
import java.util.stream.Collectors;
import org.apache.commons.io.IOUtils;
import org.apache.http.*;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.*;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.conn.ssl.AllowAllHostnameVerifier;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.impl.auth.DigestScheme;
import org.apache.http.impl.client.*;
import org.apache.http.ssl.SSLContextBuilder;
import org.testng.Assert;
import javax.net.ssl.*;
public class SOAPClientApache {
private static final String URL = "http://httpbin.org/digest-auth/auth/user/passwd";
//private static final String URL = "https://www.google.com/";
private static final String PASSWORD = "";
private static final String USER = "";
public void run() throws Exception {
HttpGet httpget = new HttpGet(URL);
HttpHost target
= new HttpHost(httpget.getURI().getHost(), 135, "https");
CredentialsProvider credsProvider = new BasicCredentialsProvider();
UsernamePasswordCredentials credentials
= new UsernamePasswordCredentials(USER, PASSWORD);
credsProvider.setCredentials(
new AuthScope(target.getHostName(), target.getPort()),
credentials);
CookieStore cookieStore = new BasicCookieStore();
//Start fix SSL (убиваем проверку сертификатов)
SSLContextBuilder builder = new SSLContextBuilder();
builder.loadTrustMaterial(null, new TrustSelfSignedStrategy() {
#Override
public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
return true;
}
});
SSLConnectionSocketFactory sslSF = new SSLConnectionSocketFactory(builder.build(),
SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
//End fix SSL
//SSL solution (ДО обхода проверки SSL)
/*CloseableHttpClient httpclient
= HttpClients.custom().setDefaultCookieStore(cookieStore)
.setDefaultCredentialsProvider(credsProvider).build();*/
CloseableHttpClient httpclient
= HttpClients.custom().setDefaultCookieStore(cookieStore)
.setDefaultCredentialsProvider(credsProvider).setSSLSocketFactory(sslSF).build();
try {
DigestScheme digestAuth = new DigestScheme();
digestAuth.overrideParamter("qop", "auth");
digestAuth.overrideParamter("nc", "0");
digestAuth.overrideParamter("cnonce", DigestScheme.createCnonce());
AuthCache authCache = new BasicAuthCache();
authCache.put(target, digestAuth);
HttpClientContext localContext = HttpClientContext.create();
localContext.setAuthCache(authCache);
CloseableHttpResponse response;
response = httpclient.execute(target, httpget, localContext);
Map<String, String> wwwAuth = Arrays
.stream(response.getHeaders("WWW-Authenticate")[0]
.getElements())
.collect(Collectors.toMap(HeaderElement::getName,
HeaderElement::getValue));
// the first call ALWAYS fails with a 401
Assert.assertEquals(response.getStatusLine().getStatusCode(), 401);
digestAuth.overrideParamter("opaque", wwwAuth.get("opaque"));
digestAuth.overrideParamter("nonce", wwwAuth.get("nonce"));
digestAuth.overrideParamter("realm", wwwAuth.get("Digest realm"));
Header authenticate = digestAuth.authenticate(credentials, httpget,
localContext);
httpget.addHeader(authenticate);
response = httpclient.execute(target, httpget, localContext);
// the 2nd call is the real deal
Assert.assertEquals(response.getStatusLine().getStatusCode(), 200);
System.out.println(IOUtils
.toString(response.getEntity().getContent(), "utf-8"));
} finally {
httpclient.close();
}
}
}
Main
public class Main {
public static void main(String[] args) throws Exception {
SOAPClientApache soapClientApache = new SOAPClientApache();
soapClientApache.run();
}
}
The solution turned out to be quite simple.
I have set the correct port for me
HttpHost target = new HttpHost(httpget.getURI().getHost(), 443, "https");
I also disabled my firewall.
I have to connect to a URL, and in that i have a link click here to download, when i click on it,it downloads a zip file which has multiple files in it. My requirement is to download that zip file using java application.I am trying to point to a URl and download the file.
I have taken the code from How to remotely login to a Jenkins server using Java?
Below is the code:
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;
import java.io.IOException;
import java.net.URI;
public class JenkinsScraper {
public 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);
return EntityUtils.toString(response.getEntity());
}
public static void main(String args[]) throws IOException {
JenkinsScraper obj = new JenkinsScraper();
String result = obj.scrape("https://info-build.gm.com/view/tools/job/MISC.DefectSummaryReport/lastSuccessfulBuild/artifact/","JZYH8B","may#2017");
System.out.print("result :: " + result);
}
}
I'm facing below exception:
Exception in thread "main" java.lang.NoSuchMethodError: org.apache.commons.codec.binary.Base64.<init>(I)V
at org.apache.http.impl.auth.BasicScheme.authenticate(BasicScheme.java:168)
Had someone worked on this type of requirement where we will have a link in the Jenkins URL, using java code we need to hit the URL and download the zip file.Do i need tp use any other API to achieve this functionality.Any suggestions would be helpful.
I have been able to successfully authentication to a service that requires ntlm authentication when using the WinHttpClients and a GET request. However when I try to do a POST I always get a 401 return code. Has anyone done this sucessfully before?
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.NTCredentials;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.WinHttpClients;
public class WindowsAuthPOst {
public static void main (String []args) throws Exception, IOException
{
org.apache.log4j.BasicConfigurator.configure();
CloseableHttpClient httpclient = WinHttpClients.createDefault();
HttpHost target = new HttpHost("SomeHost.domain", 443, "https");
HttpClientContext context = HttpClientContext.create();
HttpGet httpget = new HttpGet("/some/Service.svc");
CloseableHttpResponse response1 = httpclient.execute(target, httpget, context);
try {
HttpEntity entity1 = response1.getEntity();
} finally {
response1.close();
}
// Execute an expensive method next reusing the same context (and connection)
HttpPost httppost = new HttpPost("/some/Service.svc");
httppost.setHeader("SOAPAction", "Some Soap Action");
httppost.setEntity(new StringEntity("Soap Payload"));
CloseableHttpResponse response2 = httpclient.execute(target, httppost, context);
try {
HttpEntity entity2 = response2.getEntity();
} finally {
response2.close();
}
}
}
You can check if it is available with.
if (!WinHttpClients.isWinAuthAvailable()) {
System.out.println("Integrated Win auth is not supported!!!");
}
If not, it could be that you do not have jna.jar in your classpath. It depends on jna and will silently return false on the above if it not there, see source code.
Try with get (or options) before post. Some webservers requires that because of CORS.
https://stackoverflow.com/a/38410411/2376661
All:
I need to be able to POST a job to Jenkins using the Jenkins REST API but have not been able to get past authentication. I have been attempting to do this for a few days now and have researched answers on both this site and on the Jenkins site. I have been trying to use the Apache HttpClient with no success (even with preemptive validation). I keep getting error code 403 - forbidden. Has anyone been able to do this successfully? Here is the code that I am working with:
package stackoverflow.question;
import gsafame.sample;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.NameValuePair;
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.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
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.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
public class PreEmptiveAuth {
final Logger log = Logger.getLogger(sample.class.getCanonicalName());
private JobData jd;
private CredentialsProvider credpro;
private AuthScope as;
private UsernamePasswordCredentials upc;
private String url;
public PreEmptiveAuth(JobData jd) {
this.jd = jd;
credpro = new BasicCredentialsProvider();
as = new AuthScope(jd.getServer(), 443);
upc = new UsernamePasswordCredentials(jd.getUsername(), jd.getPassword());
credpro.setCredentials(as, upc);
url = String.format("%s:8080/jenkins/job/%s/buildWithParameters", jd.getServer(), jd.getJob());
}
public void runTagJob() throws ClientProtocolException, IOException {
log.entering(this.getClass().getCanonicalName(), "runTagJob");
log.info("Entering runTagJob");
CloseableHttpClient httpclient = HttpClients.custom()
.setDefaultCredentialsProvider(credpro).build();
HttpPost httpPost = new HttpPost(url);
List <NameValuePair> nvps = new ArrayList <NameValuePair>();
nvps.add(new BasicNameValuePair("username", jd.getUsername()));
nvps.add(new BasicNameValuePair("password", jd.getPassword()));
nvps.add(new BasicNameValuePair("apiToken", jd.getToken()));
httpPost.setEntity(new UrlEncodedFormEntity(nvps));
CloseableHttpResponse response2 = httpclient.execute(httpPost);
try {
System.out.println(response2.getStatusLine());
HttpEntity entity2 = response2.getEntity();
// do something useful with the response body
// and ensure it is fully consumed
EntityUtils.consume(entity2);
} finally {
response2.close();
}
log.info("Exiting runTagJob");
log.exiting(this.getClass().getCanonicalName(), "runTagJob");
}
public void runPreTagJob() throws ClientProtocolException, IOException {
log.entering(this.getClass().getCanonicalName(), "runPreTagJob");
log.info("Entering runPreTagJob");
HttpHost targetHost = new HttpHost(jd.getServer(), 8080, "http");
CloseableHttpClient httpclient = HttpClients.custom()
.setDefaultCredentialsProvider(credpro).build();
try {
// 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(targetHost, basicAuth);
// Add AuthCache to the execution context
HttpClientContext localContext = HttpClientContext.create();
localContext.setAuthCache(authCache);
HttpPost httpPost = new HttpPost(url);
List <NameValuePair> nvps = new ArrayList <NameValuePair>();
nvps.add(new BasicNameValuePair("username", jd.getUsername()));
nvps.add(new BasicNameValuePair("password", jd.getPassword()));
nvps.add(new BasicNameValuePair("apiToken", jd.getToken()));
httpPost.setEntity(new UrlEncodedFormEntity(nvps));
CloseableHttpResponse response2 = httpclient.execute(targetHost, httpPost, localContext);
try {
System.out.println(response2.getStatusLine());
HttpEntity entity2 = response2.getEntity();
// do something useful with the response body
// and ensure it is fully consumed
EntityUtils.consume(entity2);
} finally {
response2.close();
}
} finally {
httpclient.close();
}
log.info("Exiting runPreTagJob");
log.exiting(this.getClass().getCanonicalName(), "runPreTagJob");
}
}
The JobData object that gets passed into this class contains information like username, password, server, and job information. I hope this helps!
After researching on several sites, I managed to piece enough information together to come up with a solution. I am using older HTTP authentication code that is in some instances deprecated - but it works when nothing else would. If anyone has a better solution, I would be interested in seeing it. Anyway, here it is:
Main Class:
package stackoverflow.answer;
import java.util.List;
import java.util.Scanner;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
public class sample {
public static void main(String[] args) throws Exception {
final Logger log = Logger.getLogger(sample.class.getCanonicalName());
JobData jd = new JobData();
Scanner input = new Scanner(System.in);
try {
System.out.print("What is your user name? ");
jd.setUsername(input.next());
System.out.print("What is your password? ");
jd.setPassword(input.next());
} catch (Exception e) {
log.log(Level.SEVERE, "The system encountered an exception while attempting to login");
} finally {
input.close();
}
jd.setJob("TestREST");
jd.setServer("http://YOUR-SERVER");
jd.setPort("YOUR-PORT");
// set the parameters
List<NameValuePair> parameters = jd.getParameters();
parameters.add(new BasicNameValuePair("SONAR-TARGET", "true"));
parameters.add(new BasicNameValuePair("RELEASE", "1311.1.1"));
parameters.add(new BasicNameValuePair("REVISION", "HEAD"));
// run the job
JenkinsPoster jp = new JenkinsPoster(jd);
log.info("executing postJenkinsJob");
jp.postJenkinsJob();
log.info("executed postJenkinsJob");
}
}
The JobData class (holds information about the job you need to run)
package stackoverflow.answer;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.NameValuePair;
public class JobData {
private String username;
private String password;
private String token;
private String server;
private String port;
private String job;
private List<NameValuePair> parameters;
public JobData() {
parameters = new ArrayList<NameValuePair>();
}
public String getUsername() {return username;}
public void setUsername(String username) {this.username = username;}
public String getPassword() {return password;}
public void setPassword(String password) {this.password = password;}
public String getToken() {return token;}
public void setToken(String token) {this.token = token;}
public String getServer() {return server;}
public void setServer(String server) {this.server = server;}
public String getPort() {return port;}
public void setPort(String port) {this.port = port;}
public String getJob() {return job;}
public void setJob(String job) {this.job = job;}
public List<NameValuePair> getParameters() {return parameters;}
}
The JenkinsPoster class (contains the business logic to connect to Jenkins and POST the job)
package stackoverflow.answer;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.List;
import java.util.logging.Logger;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.auth.BasicScheme;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.util.EntityUtils;
public class JenkinsPoster {
final Logger log = Logger.getLogger(getClass().getCanonicalName());
private JobData jd;
public JenkinsPoster(JobData jobData) {
this.jd = jobData;
}
#SuppressWarnings("deprecation")
public void postJenkinsJob() throws UnsupportedEncodingException {
log.entering(getClass().getCanonicalName(), "JenkinsPoster");
// Jenkins url
String jenkinsUrl = String.format("%s:%s/jenkins", jd.getServer(), jd.getPort());
log.info("url = " + jenkinsUrl);
// Create your httpclient
DefaultHttpClient client = new DefaultHttpClient();
// Then provide the right credentials
client.getCredentialsProvider().setCredentials(new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT),
new UsernamePasswordCredentials(jd.getUsername(), jd.getPassword()));
// Generate BASIC scheme object and stick it to the execution context
BasicScheme basicAuth = new BasicScheme();
BasicHttpContext context = new BasicHttpContext();
context.setAttribute("preemptive-auth", basicAuth);
// Add as the first (because of the zero) request interceptor
// It will first intercept the request and preemptively initialize the authentication scheme if there is not
client.addRequestInterceptor(new PreemptiveAuth(), 0);
// Post the request to start the build
List<NameValuePair> parameters = jd.getParameters();
UrlEncodedFormEntity uefe = null;
String buildUrl = "";
if (parameters.isEmpty()) {
buildUrl = jenkinsUrl + "/job/" + jd.getJob() + "/build";
}
else {
buildUrl = jenkinsUrl + "/job/" + jd.getJob() + "/buildWithParameters";
uefe = new UrlEncodedFormEntity(parameters);
}
HttpPost post = new HttpPost(buildUrl);
post.setHeader("User-Agent", "Mozilla/5.0");
if (uefe != null) {
post.setEntity(uefe);
}
try {
// Execute your request with the given context
HttpResponse response = client.execute(post, context);
HttpEntity entity = response.getEntity();
log.info(EntityUtils.toString(entity));
EntityUtils.consume(entity);
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally {
client.close();
}
log.exiting(getClass().getCanonicalName(), "JenkinsPoster");
}
}
... and finally, the PreemptiveAuth class that the previous class uses to preemptively login to Jenkins.
package stackoverflow.answer;
import java.io.IOException;
import org.apache.http.HttpException;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.HttpRequestInterceptor;
import org.apache.http.auth.AuthScheme;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.AuthState;
import org.apache.http.auth.Credentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.protocol.ClientContext;
import org.apache.http.protocol.ExecutionContext;
import org.apache.http.protocol.HttpContext;
public class PreemptiveAuth implements HttpRequestInterceptor {
public void process(HttpRequest request, HttpContext context)
throws HttpException, IOException {
// Get the AuthState
AuthState authState = (AuthState) context.getAttribute(ClientContext.TARGET_AUTH_STATE);
// If no auth scheme available yet, try to initialize it preemptively
if (authState.getAuthScheme() == null) {
AuthScheme authScheme = (AuthScheme) context.getAttribute("preemptive-auth");
CredentialsProvider credsProvider = (CredentialsProvider) context
.getAttribute(ClientContext.CREDS_PROVIDER);
HttpHost targetHost = (HttpHost) context.getAttribute(ExecutionContext.HTTP_TARGET_HOST);
if (authScheme != null) {
Credentials creds = credsProvider.getCredentials(new AuthScope(targetHost.getHostName(), targetHost
.getPort()));
if (creds == null) {
throw new HttpException("No credentials for preemptive authentication");
}
authState.setAuthScheme(authScheme);
authState.setCredentials(creds);
}
}
}
}
Documentation on handling Jenkins' REST API authentication can be found here:
https://wiki.jenkins-ci.org/display/JENKINS/Authenticating+scripted+clients
I am tring to perform Digest Authentication using the HttpClient library, but I keep getting: HTTP/1.1 401 Unauthorized.
When I try the request from Firefox it works fine and I get a response correctly, so I know the server authentication is working fine.
Update: moved Working code to answer.
The following code worked for me
import java.util.Random;
import org.apache.http.HttpEntity;
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.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.auth.DigestScheme;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.client.protocol.ClientContext;
import org.apache.http.impl.client.BasicAuthCache;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.util.EntityUtils;
/**
* A simple example that uses HttpClient to execute an HTTP request against a
* target site that requires user authentication.
*/
public class RestClient {
public static void main(String args[]) throws Exception {
HttpHost targetHost = new HttpHost("localhost", 8001, "http");
DefaultHttpClient httpclient = new DefaultHttpClient();
final String userName = "admin";
final String password = "password";
httpclient.getCredentialsProvider().setCredentials(
new AuthScope("localhost", 8001),
new UsernamePasswordCredentials(userName, password));
// Create AuthCache instance
AuthCache authCache = new BasicAuthCache();
// Generate DIGEST scheme object, initialize it and add it to the local
// auth cache
DigestScheme digestAuth = new DigestScheme();
// Suppose we already know the realm name
digestAuth.overrideParamter("realm", "some realm");
// Suppose we already know the expected nonce value
digestAuth.overrideParamter("nonce", "whatever");
authCache.put(targetHost, digestAuth);
// Add AuthCache to the execution context
BasicHttpContext localcontext = new BasicHttpContext();
localcontext.setAttribute(ClientContext.AUTH_CACHE, authCache);
HttpGet httpget = new HttpGet("http://localhost:8001/rest/test");
try {
HttpResponse response = httpclient.execute(targetHost, httpget, localcontext);
HttpEntity entity = response.getEntity();
System.out.println("----------------------------------------");
System.out.println(response.getStatusLine());
if (entity != null) {
System.out.println("Response content length: " + entity.getContentLength());
}
EntityUtils.consume(entity);
} finally {
httpclient.getConnectionManager().shutdown();
}
}
}