This is my Code:
public class JavaSoapUi {
public static void main(String[] args) throws Exception {
String requestUrl = "myurl";
URLConnection connection =new URL(requestUrl).openConnection();
System.out.println( "orignal url: " + connection.getURL() );
connection.connect();
System.out.println( "connected url: " + connection.getURL() );
HttpPost httpPost = new HttpPost(requestUrl);
String username = "user";
String password = "pass";
String encoded = DatatypeConverter.printBase64Binary((username + ":" + password).getBytes("UTF-8"));
httpPost.addHeader("AUTHORIZATION", "Basic " + encoded);
HttpClient httpClient = HttpClientBuilder.create().build();
HttpResponse response = httpClient.execute(httpPost);
System.out.println("Response" + response.getStatusLine().toString());
HttpEntity entity = response.getEntity();
String responseString = EntityUtils.toString(entity, "UTF-8");
System.out.println("ResponseString" + responseString);
EntityUtils.consume(entity);
}
And I am getting output Error :HTTP/1.1 301 Moved Permanently
If I used the username and password in the SOAP UI By using the Basic Authentication I can then get the output. But when I am using the same username and password in the Java code I am getting the error.
Any one help me.
Your Authoritzation http-header looks good to me due you added the header like is defined in RFC. Furthermore if the problem was with your Authoritzation then your call must receive an Error HTTP 401 Unauthorized instead you're receiving Error HTTP 301 - Moved permanently so probably the error is with your url. Check the location http-header of your 301 error response to see the correct url for your service.
EDIT BASED ON OP COMMENT
As I said you check the location header from 301 error response, and seems that url is an https://, if you change the url, now you're receiving Error: unable to find valid certification path to requested target this is due your client has to trust in a server certificate, to do so, download the server certificate from your url and load it in the trust store of the JRE where you're executing your client with the follow command (the correct way is to add the certificate authority of your server certificate, however to perform a test load directly server certificate it's enough).
keytool -import -alias somealias -file serverCertificate.cer -keystore JRE_HOME/lib/security/cacerts
Note that keytool is inside java distribution in JAVA_HOME/bin/keytool, and default password for JRE_HOME/lib/security/cacerts trust store is changeit.
Hope this helps,
Related
I'm new to setting up certificates, the endpoint requires a valid certificate issued by I.CA. I have a .pfx with the password and can get the data from the endpoint in Postman. However I fail to achieve the same from my local server running on localhost:8080.
I'm using okhttp version 4.7.2
Here is a breakdown of the code I'm using, the loading does not cause any errors and is just for demo code adjusted. I'm having in the keystore 38 providers and only the cert under keystoreSpi that I loaded. Both key and cert are not null and seems to contain the certificate. The endpoint just return a 403 (according to docu means authorization headers ('x-api-key', 'Authorization' or 'x-client-cert') is not valid.) Since I confirmed with Postman that the api key and the token is valid (token flow is working), it can be just the missing cert. But I do not know what else is missing for the request.
KeyStore keystore = KeyStore.getInstance("PKCS12");
try (InputStream is = Files.newInputStream(Paths.get("filepath\\cert.pfx"))) {
keystore.load(is, "password".toCharArray());
} catch (Exception e) {
LOG.error(e.getMessage());
}
String alias = "myAlias";
Key key = keystore.getKey(alias, "password".toCharArray());
Certificate cert = keystore.getCertificate(alias);
PublicKey publicKey = cert.getPublicKey();
HeldCertificate heldCertificate = new HeldCertificate.Builder()
.keyPair(new KeyPair(publicKey, (PrivateKey) key))
.build();
HandshakeCertificates handshakeCerts = new HandshakeCertificates.Builder()
.addPlatformTrustedCertificates()
.heldCertificate(heldCertificate)
.build();
OkHttpClient client = new OkHttpClient().newBuilder().sslSocketFactory(handshakeCerts.sslSocketFactory(), handshakeCerts.trustManager())
.build();
Request request = new Request.Builder()
.url("https://apiendpoint/name")
.method("GET", null)
.addHeader("x-api-key", "Bearer apiKey")
.addHeader("x-correlation-id", "corId")
.addHeader("Authorization", "Bearer " + accessToken.getAccessToken())
.build();
Response response = client.newCall(request).execute();
Edit
I'm getting for response.handshake().peerPrincipal().getName() as CN the name of the endpoint I have to integrate. But response.handshake().localPrincipal().getName() is null. How do is set the localPrincipal to include the certificate that I loaded.
Here is the successful postman call.
To confirm the client authentication is working you should look at the localPrincipal in the handshake.
Call call = client.newCall(new Request.Builder().url(server.url("/")).build());
Response response = call.execute();
assertThat(response.handshake().peerPrincipal()).isEqualTo(
new X500Principal("CN=Local Host"));
assertThat(response.handshake().localPrincipal()).isEqualTo(
new X500Principal("CN=Jethro Willis"));
assertThat(response.body().string()).isEqualTo("abc");
It might be that your client certificate is not being accepted, and falling back allowing the connection but failing the request.
In your request, this header looks troubling, are you sure you provide this as is, which Authorization includes the actual access token?
.addHeader("x-api-key", "Bearer apiKey")
See https://swagger.io/docs/specification/authentication/api-keys/
The actual handshake including client happens at a layer below OkHttp, so if it's a JDK app then you might need to enable debug flags for that. Wireshark or similar can also help you debug if you are really motivated.
I am trying to send a HTTP POST request to a site with a HTTPS proxy.
I am currently doing it like that:
System.setProperty("https.protocols", "TLSv1,TLSv1.1,TLSv1.2");
HttpPost request = new HttpPost("https://example.com");
HttpHost proxy2 = new HttpHost("proxy ip here", 8080, "https");
RequestConfig config = RequestConfig.custom()
.setProxy(proxy2)
.build();
request.setConfig(config);
String json = "\"" + username + "\"";
StringEntity entity = new StringEntity(json);
request.setEntity(entity);
request.setHeader("Accept", "application/json");
request.setHeader("Content-type", "application/json");
CloseableHttpResponse response = httpclient.execute(request, context);
HttpEntity entityresponse = response.getEntity();
responseString = EntityUtils.toString(entityresponse, "UTF-8");
response.close();
httpclient.close();
But I am getting this: java.net.SocketException: Connection reset
I've tried a lot of proxies and different URLs too but the same problem is there.
It work fine if I set a HTTP URL and the http parameter in the proxy host line, but I want HTTPS :/
Any help would be appreciated.
Thanks!
If you want to call https url, you must have to install the certificate in your jre security/lib folder.
In order to install the certificate, please follow below steps:
Download InstallCert.java file from : https://confluence.atlassian.com/download/attachments/180292346/InstallCert.java?version=1&modificationDate=1315453596921
copy InstallCert.java to any location.
run: javac InstallCert.java
run: java InstallCert example.com:port
jssecacerts file will be generated
Copy it inside JAVA_HOME\jre\lib\security folder
I hope this should resolve your issue.
I'm trying to call heroku's developer api from java, but I get the following exception:
Exception in thread "main" javax.net.ssl.SSLException: hostname in certificate didn't match: <50.19.233.255> != <*.heroku.com>
My code looks like this:
HttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet("https://api.heroku.com/apps");
String token = "d6d7ea6e-6e71-4f13-b0ff-ed9ee9d56c37";
request.addHeader("Authorization", "Bearer "+token);
HttpResponse response = client.execute(request);
If I try it with curl it works fine:
curl "https://api.heroku.com/apps" -H"Authorization: Bearer d6d7ea6e-6e71-4f13-b0ff-ed9ee9d56c37"
Why does the java code act differently to curl?
P.S. I'm aware that others have asked this questions, but all the answers, e.g:
https://stackoverflow.com/a/7266768
https://stackoverflow.com/a/3904473
https://stackoverflow.com/a/25356821
suggest that I should override the certificate hostname check, which surely defeats the point (and certainly isn't production-ready)?
This problem is described in Apache HttpClient resolving domain to IP address and not matching certificate.
It appears to be a bug in the version of HTTPClient you are using, where it compares the target IP instead of the target hostname with the subject certificate. Please use a fixed version of HTTPClient instead.
I have write a static post method with apache httpClient:
public class HttpPost {
public static HttpPostResult post(String url, String xml) throws IOException {
Logger.getAnonymousLogger().log(Level.INFO, url + "|" + xml);
HttpClient httpClient = new HttpClient();
HttpPostResult httpPostResult = new HttpPostResult();
PostMethod postMethod = new PostMethod(url);
StringRequestEntity stringRequestEntity = new StringRequestEntity(xml,"xml","utf-8");
postMethod.setRequestEntity(stringRequestEntity);
httpClient.executeMethod(postMethod);
httpPostResult.setStatus(postMethod.getStatusCode());
httpPostResult.setResponseStr(postMethod.getResponseBodyAsString());
return httpPostResult;
}
}
This method worked just fine when I test it stand-alone, but once I build it to a maven dependency and involve it in a http servlet, it just not work and the response string become:
<html>
<head><title>400 The SSL certificate error</title></head>
<body bgcolor="white">
<center><h1>400 Bad Request</h1></center>
<center>The SSL certificate error</center>
<hr><center>nginx</center>
</body>
</html>
Seems remote host is using a nginx and I guess maybe there is some SSL trust issues occurred, but the remote host is trusted (with CA signed by trustful agency) it's https://api.mch.weixin.qq.com/pay/orderquery
What should be the problem?
I fixed this by add some config in glassfish domain.xml with:
<jvm-options>-Djavax.net.ssl.keyStorePassword=changeit</jvm-options>
<jvm-options>-Djavax.net.ssl.trustStorePassword=changeit</jvm-options>
post this in case may be helpful to some one comes with same issue.
Note that changeit is the default password for glassfish keystore.
I'm developing a mobile app that involves parsing data from JSON object via Kimono Labs. I am having problem when it comes to SSL and certificates when accessing the APIs at Kimono Labs.
According to Kimono Labs, calling the API requires setting the header "Authorization: Bearer " header at the call.
GET Request
Calling an auth API using a GET request is just like calling any kimono api, but you will additionally need to pass your secure token in the Authentication request header, like so: Authorization: Bearer {YOUR_SECURE_TOKEN}
I'm using the following code to get InputStream
HttpUriRequest request = new HttpGet(apiURL);
request.addHeader("authorization", "Bearer " + securityToken);
HttpClient httpclient = new DefaultHttpClient();
InputStream is = httpclient.execute(request).getEntity().getContent();
Executing this code gives me an exception: javax.net.ssl.SSLPeerUnverifiedException: No peer certificate
Alternatively I tried implementing with the following code:
URL url = new URL(apiURL);
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestProperty("Authorization", "Bearer " + securityToken);
urlConnection.setRequestMethod("GET"); urlConnection.setConnectTimeout(activity.getResources().getInteger(R.integer.internet_timeout)); urlConnection.setReadTimeout(activity.getResources().getInteger(R.integer.internet_timeout));
InputStream inputStream = urlConnection.getInputStream();
With this code I am having the exception javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
Any ideas?
I am able to "hack" solve it by allowing all certificates via CustomTrustManager and CustomAllVerifier returning true for all attempts but heard this is totally unsafe and is not recommended for production. Is this true in my case?
Thank you in advance.
I ran into exactly the same problem with a node.js build using kimono as api. The problem is that the intermediate signed cert is not trusted by Mozilla, ergo nodejs throws a leaf error.
I solved it by doing the following, find which cert is being used, download the pem for it and add it to your root CA's before doing the request to kimono, its a hell of a lot safer than disabling TLS/SSL security checks.
Just a heads up! Turned out that this is a temporary problem with kimonolabs' server.