I am using this library - Java-WebSocket
I am using secure websockets and trying to pass a http cookie in the WebSocketClient :
HashMap<String, String> header = new HashMap<String, String>();
header =this.sessionCookie;//session cookie is obtained from https authentication
new WebSocketClient( new URI(serverURL), new Draft_17(), header); //server url is wss://xyzsomething:1100
But this doesn't seem to be working (connection fails). Any ideas as to what am I doing wrong ? Am I not setting the cookie right in the websocketclient ?
So the problem with my socket was that I had to exchange certificates with the server. I had to execute the following function before opening the websocket :
private void trustServer() throws KeyManagementException, NoSuchAlgorithmException {
// Create a trust manager that does not validate certificate chains
TrustManager[] certs = new TrustManager[]{ new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new java.security.cert.X509Certificate[]{};
}
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {}
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException{ }
}};
SSLContext sslContext = null;
sslContext = SSLContext.getInstance( "TLS" );
sslContext.init( null, certs, new java.security.SecureRandom() );
this.setWebSocketFactory(new DefaultSSLWebSocketClientFactory(sslContext));
}
Related
I am trying to connect server using https url But still could not understand how should I add SSL certificate to jersey client
private static String post() throws Exception {
String url ="https://www.test.lk/services/erl/es/erl/view/index.action";
Client client =createClient();
try {
return client
.target(url)
.request()
.get()
.readEntity(String.class);
} finally {
client.close();
}
}
private static Client createClient() throws Exception {
SSLContext ctx = SSLContext.getInstance("SL");
ctx.init(null, getTrustManager(), new SecureRandom());
HostnameVerifier verifier = new HostnameVerifier() {
#Override
public boolean verify(String hostName, SSLSession sslSession) {
return true;
}
};
return ClientBuilder.newBuilder().sslContext(ctx).hostnameVerifier(verifier).build();
}
private static TrustManager[] getTrustManager() {
return new TrustManager[] { new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
// Trust all servers
}
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
// Trust all clients
}
} };
}
I found the solution. I just need to add certificate to the java KeyStore This helped me
I have to consume a rest service which is running on HTTPs. The producer has given me the certificate and method arguments. Could you please let me know how to consume the service and how to use the certificate in code. I am using Spring 4, Java 8. Please share the code snippet.
If it is just an one way SSL where consumer validates the identity of the service, you simply need to import the certificate provided by the service(producers certificate) to you trust store (CACerts file) or write your own trust manager.
For 2 Way SSL where service also authenticate the client's identity, you not only need to validate the identity of the service, you also need to send your certificate to the service so that service can take decision on it.
Following snippet is for 2 way SSL, but you can easily adopt it to 1 way SSL by commenting out the portion which sends client certicate to the server.
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager(){
public X509Certificate[] getAcceptedIssuers(){return null;}
public void checkClientTrusted(X509Certificate[] certs, String authType){}
public void checkServerTrusted(X509Certificate[] certs, String authType){}
}};
// Install the all-trusting trust manager
RestTemplate restTemplate = new RestTemplate();
try {
String keyPassphrase = "changeit";
KeyStore keyStore = KeyStore.getInstance("jks");
keyStore.load(new FileInputStream("c:\\jks\\client.jks"), keyPassphrase.toCharArray());
KeyManagerFactory kmfactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmfactory.init(keyStore, keyPassphrase.toCharArray());
KeyManager[] keyManager = kmfactory.getKeyManagers();
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(keyManager, trustAllCerts, new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier(new javax.net.ssl.HostnameVerifier(){
public boolean verify(String hostname,
javax.net.ssl.SSLSession sslSession) {
if (hostname.equals("localhost")) {
return true;
}
return false;
}
});
} catch (Exception e) {
;
}
System.out.println("Testing listAllUsers API-----------");
restTemplate.setErrorHandler(new ResponseErrorHandler(){
#Override
public void handleError(ClientHttpResponse rs) throws IOException {
InputStream in = rs.getBody();
String str = new String("");
int len =0;
while((len = in.available()) > 0){
byte[] bytes = new byte[len];
in.read(bytes);
str = str + new String (bytes, "UTF-8");
}
System.out.println(str);
}
#Override
public boolean hasError(ClientHttpResponse rs) throws IOException {
return false;
}
});
try{
String usersMap = restTemplate.getForObject(REST_SERVICE_URI+"/user/shailendra/", String.class);`
I want access a SOAP webservice url having https hosted in a remote vm. I am getting an exception while accessing it using HttpURLConnection.
Here's my code:
import javax.net.ssl.*;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
/**
* Created by prasantabiswas on 07/03/17.
*/
public class Main
{
public static void main(String [] args)
{
try
{
URL url = new URL("https://myhost:8913/myservice/service?wsdl");
HttpURLConnection http = null;
if (url.getProtocol().toLowerCase().equals("https")) {
trustAllHosts();
HttpsURLConnection https = (HttpsURLConnection) url.openConnection();
https.setHostnameVerifier(DO_NOT_VERIFY);
http = https;
} else {
http = (HttpURLConnection) url.openConnection();
}
String SOAPAction="";
// http.setRequestProperty("Content-Length", String.valueOf(b.length));
http.setRequestProperty("Content-Type", "text/xml; charset=utf-8");
http.setRequestProperty("SOAPAction", SOAPAction);
http.setRequestMethod("GET");
http.setDoOutput(true);
http.setDoInput(true);
OutputStream out = http.getOutputStream();
}
catch (Exception e)
{
e.printStackTrace();
}
}
final static HostnameVerifier DO_NOT_VERIFY = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
private static void trustAllHosts() {
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new java.security.cert.X509Certificate[] {};
}
public void checkClientTrusted(X509Certificate[] chain,
String authType) throws CertificateException
{
}
public void checkServerTrusted(X509Certificate[] chain,
String authType) throws CertificateException {
}
} };
// Install the all-trusting trust manager
try {
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection
.setDefaultSSLSocketFactory(sc.getSocketFactory());
} catch (Exception e) {
e.printStackTrace();
}
}
}
I'm getting the following exception:
javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: Certificates does not conform to algorithm constraints
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1949)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1509)
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:979)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:914)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)
at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:559)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
at sun.net.www.protocol.http.HttpURLConnection.getOutputStream0(HttpURLConnection.java:1283)
at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:1258)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:250)
at Main.main(Main.java:35)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
Caused by: java.security.cert.CertificateException: Certificates does not conform to algorithm constraints
at sun.security.ssl.AbstractTrustManagerWrapper.checkAlgorithmConstraints(SSLContextImpl.java:1055)
at sun.security.ssl.AbstractTrustManagerWrapper.checkAdditionalTrust(SSLContextImpl.java:981)
at sun.security.ssl.AbstractTrustManagerWrapper.checkServerTrusted(SSLContextImpl.java:923)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1491)
... 18 more
Tried different solution from the google search, Non of them worked. I want to avoid using keytool because I will be running my tests on different vm.
Does anyone have any solution for this?
Using X509ExtendedTrustManager instead of X509TrustManager() solved the problem. Here's the example:
public void trustAllHosts()
{
try
{
TrustManager[] trustAllCerts = new TrustManager[]{
new X509ExtendedTrustManager()
{
#Override
public java.security.cert.X509Certificate[] getAcceptedIssuers()
{
return null;
}
#Override
public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType)
{
}
#Override
public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType)
{
}
#Override
public void checkClientTrusted(java.security.cert.X509Certificate[] xcs, String string, Socket socket) throws CertificateException
{
}
#Override
public void checkServerTrusted(java.security.cert.X509Certificate[] xcs, String string, Socket socket) throws CertificateException
{
}
#Override
public void checkClientTrusted(java.security.cert.X509Certificate[] xcs, String string, SSLEngine ssle) throws CertificateException
{
}
#Override
public void checkServerTrusted(java.security.cert.X509Certificate[] xcs, String string, SSLEngine ssle) throws CertificateException
{
}
}
};
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
// Create all-trusting host name verifier
HostnameVerifier allHostsValid = new HostnameVerifier()
{
#Override
public boolean verify(String hostname, SSLSession session)
{
return true;
}
};
// Install the all-trusting host verifier
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
}
catch (Exception e)
{
log.error("Error occurred",e);
}
}
Edit : Understand the vulnerability this would cause before using it. This is by no means recommended for production use.
The best way is to create a dummy trustmanager that trusts everything.
TrustManager[] dummyTrustManager = new TrustManager[] { new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
} };
Then use the dummy trustmanager to initialize the SSL Context
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, dummyTrustManager, new java.security.SecureRandom());
Finally use the SSLContext to open connection
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
URL url = new URL("https://myhost:8913/myservice/service?wsdl");
This question has already been answered here in more detail
Java: Overriding function to disable SSL certificate check
Update:
Above issue is due to certificate signature algorithm not being supported by Java. As per this post, later releases of Java 8 have disabled md5 algorithm.
To enable md5 support, locate java.security file under <jre_home>/lib/security
and locate the line (535)
jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024,
and remove MD5
Try with Apache HTTP client, this works for me.
SSLContextBuilder builder = new SSLContextBuilder();
builder.loadTrustMaterial(null, new TrustStrategy() {
public boolean isTrusted(final X509Certificate[] chain, String authType) throws CertificateException {
return true;
}
});
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(builder.build());
CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
// GET or POST request with the client
...
Instead of using HttpsURLConnection.setDefaultSSLSocketFactory and your own implementation of TrustManager or X509ExtendedTrustManager, you can use TrustManagerFactory with a KeyStore with the certificate that issued the certificate you need to trust (for a self-signed certificate, this is the same as the host certificate) and call HttpsURLConnection.setSSLSocketFactory on the specific instance. This is both less code and avoids the security problems with trusting all HTTPS certicates.
In main:
if (url.getProtocol().toLowerCase().equals("https")) {
HttpsURLConnection https = (HttpsURLConnection) url.openConnection();
https.setSSLSocketFactory(createSSLSocketFactory());
http = https;
}
The method createSSLSocketFactory looks like this:
private static SSLSocketFactory createSSLSocketFactory() {
File crtFile = new File("server.crt");
Certificate certificate = CertificateFactory.getInstance("X.509").generateCertificate(new FileInputStream(crtFile));
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null, null);
keyStore.setCertificateEntry("server", certificate);
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustManagerFactory.getTrustManagers(), null);
return sslContext.getSocketFactory();
}
I'm trying to configure org.apache.http.client.HttpClient to work with https. This is the client configuration:
TrustManager[] trustManagers = new TrustManager[] { new DummyTrustManager() };
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(keyManagers, trustManagers, null);
SSLSocketFactory sf = new SSLSocketFactory(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
Scheme scheme = new Scheme("https", 443, sf);
SchemeRegistry registry = new SchemeRegistry();
registry.register(scheme);
ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager(registry);
DefaultHttpClient client = new DefaultHttpClient(cm, httpParameters);
This is the code of DummyTrustManager:
public static class DummyTrustManager implements X509TrustManager {
#Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
#Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
#Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
}
And when I send request, I get
`javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated`
What could be the problem?
You also need to adjust the TrustStrategy:
TrustStrategy acceptingTrustStrategy = new TrustStrategy() {
#Override
public boolean isTrusted(X509Certificate[] certificate, String authType) {
return true;
}
};
SSLSocketFactory sf = new SSLSocketFactory(acceptingTrustStrategy, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
...
see a full example at: http://www.baeldung.com/httpclient-ssl
My client is successfully getting response from server through HTTP.
SOAPConnectionFactory sfc = SOAPConnectionFactory.newInstance();
SOAPConnection connection = sfc.createConnection();
SOAPMessage soapMessageResponse = connection.call(soapRequest, new URL(serviceLocation));
I want SSL communication between client/server.
In another project I am successfully creating SSLSocketFactory from a KeyStore and TrustManagerFactory for SSL handshake.
How can I use SSLSocketFactory code in webservice client to make client SSL communication successful to call server.
I'm pretty sure it will use the default SSLContext. You can change that with SSLContext.setDefault().
SSLContext c = SSLContext.getInstance("SSL");
TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX");
tmf.init(yourKeystore);
TrustManager tm = tmf.getTrustManagers()[0];
tm.
c.init(null, tm, null);
Here are some other values for the string parameters above.
If you need more complete control, you can implement your own subclass of SSLContext which returns your own implementation of SSLSocketFactory and set that SSLContext as the default:
public class MySSLContext extends SSLContext {
private SSLContext wrapped;
private SSLSocketFactory mySocketFactory;
public MySSLContext(SSLContext toWrap, SSLSocketFactory mySocketFactory) {
wrapped = toWrap;
this.mySocketFactory = mySocketFactory;
}
public SSLSocketFactory getSocketFactory() {
return mySocketFactory;
}
public SSLSessionContext getClientSessionContext() {
return wrapped;
}
// other delegates
}
Hi if you add this code your webservice class ı think your problem will be solve .
`
//just put it your somewhere
public static class miTM implements javax.net.ssl.TrustManager,
javax.net.ssl.X509TrustManager {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public boolean isServerTrusted(
java.security.cert.X509Certificate[] certs) {
return true;
}
public boolean isClientTrusted(
java.security.cert.X509Certificate[] certs) {
return true;
}
public void checkServerTrusted(
java.security.cert.X509Certificate[] certs, String authType)
throws java.security.cert.CertificateException {
return;
}
public void checkClientTrusted(
java.security.cert.X509Certificate[] certs, String authType)
throws java.security.cert.CertificateException {
return;
}
}
// CAll This function in your webservice class .
private static void trustAllHttpsCertificates() throws Exception {
// Create a trust manager that does not validate certificate chains:
javax.net.ssl.TrustManager[] trustAllCerts =
new javax.net.ssl.TrustManager[1];
javax.net.ssl.TrustManager tm = new miTM();
trustAllCerts[0] = tm;
javax.net.ssl.SSLContext sc =
javax.net.ssl.SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, null);
javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(
sc.getSocketFactory());
}
This line of code will not work in case of SSL.
SOAPMessage soapMessageResponse = connection.call(soapRequest, new URL(serviceLocation));
Create trustmanager and keymanagers from here.
In order to get response through SSL from axis2 webservice you need to open streams like given here