Skip to content

Instantly share code, notes, and snippets.

@cbweixin
Created July 24, 2015 16:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cbweixin/a095055617b5f1f0208d to your computer and use it in GitHub Desktop.
Save cbweixin/a095055617b5f1f0208d to your computer and use it in GitHub Desktop.
how to use jax-rs rest client to accept all certifications. the way is different from the way which used by org.apache.httpclient
package com.intuit.sb.dispatcher;
import com.intuit.qbn.util.ids.CompanyId;
import com.intuit.sb.dispatcher.common.domain.CompanyShardVHost;
import com.intuit.sb.dispatcher.common.error.ServiceErrorBean;
import com.intuit.sb.dispatcher.error.ServiceException;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSession;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Response;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.KeyStore;
import java.util.ArrayList;
import java.util.List;
public class DispatcherLib {
// TODO use moco or wiremock to emulate server
// TODO See if https certificates an issue
public static String dispatcherServiceUrl;
private static final Logger logger = LoggerFactory.getLogger(DispatcherLib.class);
public DispatcherLib() {
setEnv();
}
public static void main(String[] args) {
DispatcherLib lib = new DispatcherLib();
lib.makeHttpCall("realm/11111111/qbo", "GET");
}
// TODO this should probably be called in the constructor, and this object needs to be singleton
// What do you mean by singleton?
public static void setEnv() { // env = prod, qa, etc....
String env;
if ((env = System.getProperty("env")) == null) {
env = "app"; // default to localhost
}
try {
ClassLoader classLoader = DispatcherLib.class.getClassLoader();
System.getProperties()
.load(classLoader.getResourceAsStream("dispatcher." + env + ".properties"));
} catch (FileNotFoundException error) {
logger
.error("Cannot locate configuration file {0}", "dispatcher." + env + ".properties");
error.printStackTrace();
} catch (IOException error) {
logger.error("Error opening file {0}", "dispatcher." + env + ".properties");
error.printStackTrace();
}
dispatcherServiceUrl = System.getProperty("url");
}
/**
* Default appId is "qbo".
* QBNResiliencyResolver / Edge router request for shard/host and data center info.
* Endpoint: v1/dispatcher/realm/{realmId}/{appId}
*
* @param companyId
* @return CompanyShardVHost
* @throws CompanyShardVHost
*/
public static CompanyShardVHost getCompanyShardVHost(CompanyId companyId)
throws ServiceException {
return getCompanyShardVHost("qbo", companyId);
}
/**
* QBNResiliencyResolver / Edge router request for shard/host and data center info.
* Endpoint: v1/dispatcher/realm/{realmId}/{appId}
*
* @param appId
* @param companyId
* @return CompanyShardVHost
* @throws ServiceException
*/
public static CompanyShardVHost getCompanyShardVHost(String appId, CompanyId companyId)
throws ServiceException {
try {
Response response = makeHttpCall("realm/" + companyId.getId() + "/" + appId, "GET");
int status = response.getStatus();
if (status == Response.Status.OK.getStatusCode()) {
return response.readEntity(CompanyShardVHost.class);
} else {
logError(appId, companyId, status);
}
throw new ServiceException(response.readEntity(ServiceErrorBean.class), status);
} catch (ServiceException error) { // TODO Do we need this? Yes,
// in order to throw ServiceException error instead of an Exception
logger.error(error.getServiceErrorBean().getMessage());
throw error;
} catch (Exception error) {
logger.error(
"Exception at endpoint: " + dispatcherServiceUrl + "realm/" + companyId.getId()
+ "/" + appId);
throw error;
}
}
private static void logError(String appId, CompanyId companyId, int responseStatus) {
if (responseStatus == Response.Status.NO_CONTENT.getStatusCode()) // 204 No Content
{
logger.error(
"204 No Content. Endpoint: " + dispatcherServiceUrl + companyId.getId() + "/"
+ appId);
} else if (responseStatus == Response.Status.NOT_FOUND.getStatusCode()) {
logger.error(
"404 Not Found. Endpoint: " + dispatcherServiceUrl + companyId.getId() + "/"
+ appId);
} else if (responseStatus == Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()) {
logger.error(
"500 Internal Server Error. Endpoint: " + dispatcherServiceUrl + companyId.getId()
+ "/" + appId);
}
}
/**
* Default appId is "qbo"
* Retrieve mapping of companyIds to shards
* Endpoint: v1/dispatcher/shard/{appId}/{shardId}
*
* @param companyIds
* @return List<CompanyShardVHost>
* @throws ServiceException
*/
public List<CompanyShardVHost> getCompanyShardVHostsFromCompanyIds(List<CompanyId> companyIds)
throws ServiceException {
return getCompanyShardVHostsFromCompanyIds("qbp", companyIds);
}
/**
* Retrieve mapping of companyIds to shards
* Endpoint: v1/dispatcher/shard/{appId}/{shardId}
*
* @param appId
* @param companyIds
* @return List<CompanyShardVHost>
* @throws ServiceException
*/
public List<CompanyShardVHost> getCompanyShardVHostsFromCompanyIds(
String appId, List<CompanyId> companyIds) throws ServiceException {
try {
//TODO Define own class as a Map<CompanyId, CompanyShardVHost> to avoid redundancy
// (don't need realm id in value)
List<CompanyShardVHost> list = new ArrayList<CompanyShardVHost>();
for (CompanyId companyId : companyIds) {
list.add(getCompanyShardVHost(appId, companyId));
}
return list;
} catch (ServiceException error) {
throw error;
} catch (Exception error) {
throw error;
}
}
/**
* Default appId is "qbo".
* QBNResiliencyResolver / Edge router request for shard/host and data center info.
* Endpoint: v1/dispatcher/realm/{realmId}/{appId}
*
* @param companyId
* @return
* @throws ServiceException
*/
public static String getHostFromCompanyId(CompanyId companyId) throws ServiceException {
return getHostFromCompanyId("qbo", companyId);
}
/**
* QBNResiliencyResolver / Edge router request for shard/host and data center info.
* Endpoint: v1/dispatcher/realm/{realmId}/{appId}
*
* @param appId
* @param companyId
* @return String
* @throws ServiceException
*/
public static String getHostFromCompanyId(String appId, CompanyId companyId)
throws ServiceException {
try {
Response response = makeHttpCall("realm/" + companyId.getId() + "/" + appId, "GET");
int status = response.getStatus();
if (status == Response.Status.OK.getStatusCode()) {
return response.readEntity(CompanyShardVHost.class).getHost();
} else {
logError(appId, companyId, status);
}
throw new ServiceException(response.readEntity(ServiceErrorBean.class), status);
}
/* Not sure we need this
catch (ServiceException error) {
logger.error(error.getServiceErrorBean().getMessage());
throw error;
} */ catch (Exception error) {
logger.error(
"Exception at endpoint: " + dispatcherServiceUrl + companyId.getId() + "/" + appId);
throw error;
}
}
/**
* Default appId is "qbo"
* Retrieve mapping of companyIds to host name
* Endpoint: v1/dispatcher/shard/{appId}/{shardId}
*
* @param companyIds
* @return List<String>
* @throws ServiceException
*/
public static List<String> getHostsFromCompanyIds(List<CompanyId> companyIds)
throws ServiceException {
return getHostsFromCompanyIds("qbo", companyIds);
}
/**
* Retrieve mapping of companyIds to host name
* Endpoint: v1/dispatcher/shard/{appId}/{shardId}
*
* @param appId
* @param companyIds
* @return List<String>
* @throws ServiceException
*/
public static List<String> getHostsFromCompanyIds(String appId, List<CompanyId> companyIds)
throws ServiceException {
try {
List<String> list = new ArrayList<String>();
for (CompanyId companyId : companyIds) {
list.add(
getHostFromCompanyId(
appId, companyId)); // TODO make the batch call /realm/batch/{appId},
}
// and pass in list of realm Ids in the body of the request. You might
// have to add checks around batch size, etc...
return list;
} catch (ServiceException error) {
throw error;
}
}
/**
* Default appId is "qbo"
* Create or move/update company.
* Endpoint: v1/dispatcher/realm/{appId}/{shardId}/{hostUrl}/{realmId}
*
* @param shardId
* @param companyId
* @return Returns true for successful company creation or update. Returns false if error is
* thrown.
*/
public static boolean createOrUpdateCompany(CompanyId companyId, int shardId, String vHost)
throws Exception {
return createOrUpdateCompany("qbo", companyId, shardId, vHost);
}
/**
* Create or move/update company.
* Endpoint: v1/dispatcher/realm/{appId}/{shardId}/{hostUrl}/{realmId}
*
* @param appId
* @param companyId
* @param shardId
* @param vHost
* @return Returns true for successful company creation or update. Returns false if error is
* thrown.
* @throws ServiceException
*/
public static boolean createOrUpdateCompany(
String appId, CompanyId companyId, int shardId, String vHost) throws ServiceException {
try {
Response response = makeHttpCall(
"realm/" + appId + "/" + shardId + "/" + vHost + "/" + companyId.getId(), "POST");
int status = response.getStatus();
if (status == Response.Status.OK.getStatusCode()) {
logger.info("Shard updated for company {0}", companyId.getId());
} else if (status == Response.Status.CREATED.getStatusCode()) {
logger.info(
"Entry created for company {} app {} shard {}", companyId.getId(), appId,
shardId);
} else {
logError(appId, companyId, status);
return false;
}
return true;
// Do we need this ? throw new ServiceException(ErrorEnum.UNKNOWN_COMPANY_AND_APP_ID,
// status);
}
/* TODO Who's going to throw Service Exception
catch (ServiceException error) {
logger.error(error.getServiceErrorBean().getMessage());
throw error;
}
*/ catch (Exception exception) {
//TODO Convert exception to ServiceException and throw it
logger.error(
"Exception at endpoint: " + dispatcherServiceUrl + companyId.getId() + "/" + appId);
throw exception;
}
}
/**
* Helper method that sends the jersey rest call and retrieves the response
*
* @param endpoint
* @param methodType
* @return Response
*/
private static Response makeHttpCall(String endpoint, String methodType) {
dispatcherServiceUrl =
"https://ci-develop-dispatcher-service.sbfs-acct-sbg-dispatcher-dev.a.intuit" +
".com/webapp/v1/dispatcher/";
logger.debug("endpoint: " + dispatcherServiceUrl + endpoint);
MySecureProtocolSocketFactory contextFactory = new MySecureProtocolSocketFactory();
Client client = null;
ClientBuilder builder = ClientBuilder.newBuilder();
try {
// builder.keyStore(
// loadStore("/Users/xwei/Documents/mykey/dispatcherkey", "123456"),
// "123456");
builder.hostnameVerifier(new NoopHostnameVerifier()).sslContext(
contextFactory.getSslContext());
client = builder.build();
} catch (Exception e) {
e.printStackTrace();
}
WebTarget target = client.target(dispatcherServiceUrl).path(endpoint);
Response response = null;
switch (methodType) {
case "GET":
response = target.request().get();
break;
case "POST":
response = target.request().post(null);
break;
default:
response = null;
}
System.out.println(response.getStatus());
CompanyShardVHost companyShardVHost = response.readEntity(CompanyShardVHost.class);
System.out.println(companyShardVHost.getRealmId());
System.out.println(companyShardVHost.getShard());
System.out.println(companyShardVHost.getHost());
System.out.println(companyShardVHost.getAppId());
return response;
}
// if we got any CA authorized cert, then we need to load it as 'keystore', also
// we need to load 'truststore'. but for accepting all cert purpose, it is no use
// TODO : Fix Me. use me later
private static KeyStore loadStore(String trustStoreFile, String password) throws Exception {
KeyStore store = KeyStore.getInstance("JKS");
store.load(new FileInputStream(trustStoreFile), password.toCharArray());
return store;
}
}
// since we already used 'NoopHostnameVerifier', we don't need to implement our own verfier anymore
class VerifyEverythingHostnameVerifier implements HostnameVerifier {
@Override
public boolean verify(String string, SSLSession sslSession) {
return true;
}
}
package com.intuit.sb.dispatcher;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
/**
* Created by xwei on 7/22/15.
*/
public class MySecureProtocolSocketFactory {
private SSLContext sslContext = null;
private SSLContext createSSLContext() {
SSLContext sslContext1 = null;
try {
sslContext1 = SSLContext.getInstance("TLS");
sslContext1.init(
null, new TrustManager[] {new TrustAnyTrustManager()}, new SecureRandom());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
}
return sslContext1;
}
public SSLContext getSslContext() {
if (this.sslContext == null) {
this.sslContext = createSSLContext();
}
return this.sslContext;
}
private static class TrustAnyTrustManager implements X509TrustManager {
@Override
public void checkClientTrusted(
X509Certificate[] x509Certificates, String s) throws CertificateException {
}
@Override
public void checkServerTrusted(
X509Certificate[] x509Certificates, String s) throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
// return null;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment