Reusing a Java REST client as an RTC service. Unable to login in RTC from an RTC service
Hi! I'm trying to login to my local RTC server with help of some legacy code that is said to work fine, but I receive the javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure all the time.
The trick is that I am trying to write a wrapper plugin for RTC web interface that would proxy calls from WebUI to a REST client implementation that was used to work with repository via REST from a remote client. So I wrote a MODELLED_REST service plugin and embedded the legacy code in it. It compiles and runs, but when the legacy method tries to login, it gets a handshake_failure error. Is what I am doing possible at all? I'll be grateful for any hints on this.
Is there a smarter way to reuse the legacy code? This restClient has a lot of logic in it and I'd like to make as much use of it as possible.
UPD: When I try to login from my service running on Jetty to a different instance of RTC running on Tomcat it works fine with Scheme set on port 443. The login URL I use there is https://127.0.0.1:9443/ccm/authenticated/identity. But Jetty doesn't have this kind of a link and uses https://127.0.0.1:7443/jazz/.. to address everything. So the URL for Jetty is https://127.0.0.1:7443/jazz/authenticated/identity
Here is the code that is used to login (the bold line is the one where the Exception is thrown):
public boolean loginRTC() {
HttpResponse response;
logger.info("trying to log in");
try {
httpClient = getHttpClient();
logger.info("getting cookies");
cookieStore = new BasicCookieStore();
localContext = new BasicHttpContext();
localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
//this link in browser redirects me to the login page
HttpGet httpGetID = new HttpGet("https://127.0.0.1:7443/jazz/authenticated/identity");
response = httpClient.execute(httpGetID, localContext);
logger.info(response.getStatusLine().toString());
httpGetID.abort();
logger.info("cookies:");
List<Cookie> cookies1 = cookieStore.getCookies();
for (Cookie cookie : cookies1) {
logger.info("\t" + cookie.getName() + " : " + cookie.getValue());
}
logger.info("send username and password");
List<NameValuePair> authFormParams = new ArrayList<NameValuePair>();
authFormParams.add(new BasicNameValuePair("j_username", "ADMIN"));
authFormParams.add(new BasicNameValuePair("j_password", "ADMIN"));
UrlEncodedFormEntity entity;
entity = new UrlEncodedFormEntity(authFormParams, "UTF-8");
HttpPost httpPostAuth = new HttpPost(rtcUrl + LOGIN_CHECK_URL);
httpPostAuth.setEntity(entity);
response = httpClient.execute(httpPostAuth, localContext);
logger.info(response.getStatusLine().toString());
httpPostAuth.abort();
// retrieve new cookies
HttpGet httpGetCookie = new HttpGet(rtcUrl + LOGIN_FORM_URL);
response = httpClient.execute(httpGetCookie, localContext);
logger.info(response.getStatusLine().toString());
httpGetCookie.abort();
if (checkAuthorized()) {
logger.info("login SUCCESSFUL");
return true;
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
logger.info("login FAILED");
return false;
}
and getHttpClient is as follows:
private HttpClient getHttpClient() throws RequestException {
try {
SSLSocketFactory socketFactory = new SSLSocketFactory(
new TrustStrategy() {
public boolean isTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
return true;
}
}, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
Scheme sch = new Scheme("https", 443, socketFactory);
ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager();
cm.setMaxTotal(MAX_CONNECTION_COUNT);
HttpClient result = new DefaultHttpClient(cm);
result.getConnectionManager().getSchemeRegistry().register(sch);
return result;
} catch (Exception e) {
String msg = "Couldn't set SSL trust strategy: " + e.getMessage();
logger.error(msg, e);
throw new RequestException(msg);
}
}
2 answers
Comments
No, that doesn't seem to be the reason. When I try to login from my service running on Jetty to a different instance of RTC running on Tomcat it works fine with Scheme set on port 443. The login URL I use there is https://127.0.0.1:9443/ccm/authenticated/identity. But Jetty doesn't have this kind of a link and uses https://127.0.0.1:7443/jazz/.. to address everything. So the URL for Jetty is https://127.0.0.1:7443/jazz/authenticated/identity. I've tried to change the Scheme port to 7443 with Jetty, but still no good.
P.S. The rtcUrl value is https://127.0.0.1:7443/jazz/ and the LOGIN_FORM_URL is authenticated/identity. The URL in the HttpGet request is a result of their concatenation. I just provided it in plain text for better understanding.
The code I've seen that tries to do what you're doing (accept all certificate and trust all hosts) looks a little different; it uses TrustManager instead of TrustStrategy. For example, see http://javaskeleton.blogspot.com/2010/07/avoiding-peer-not-authenticated-with.html I'm afraid that's all the advice I have.
Is it possible that the plugin tries to login to host but the host is not ready to accept the connections yet? As far as I get it, the initialization of the restClient is done during server startup. If so, how can I postpone it?
I altered the code so that the first attempt to login is made when the first "set" request is recieved. I've also replaced the getHttpClient code with the one in your article. Still javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure Looks like this has something to do with Jetty. It works when deployed on Tomcat.
Sorry, I'm out of ideas.
May be that one of the server's (to which you're able to talk to..) security certificate is already installed and the other one's not..
To overcome this, you must open the server on the browser, export the security certificate from there.. Import this certificate into the jdk's certificate store.. (import into all, if you have more than one certificate store, under jre, jdk folder... also if you have more than one jdk/jre folders, wherever you have the certificate store..)