I am currently working in a dev environment where we are using self signed certificates. I've been trying for a little over a day now to get jersey to ignore the self signed certificate. This is purely for a POC environment, I wouldn't dream of doing thi sin production. While I've found many answers on the interweb about how to make this work, something is still off.
Here's my current test class:
public class JerseyTestClient {
private static final Logger LOG = Logger.getLogger(JerseyTestClient.class.getName());
public static void sendTestRequest() {
try {
Client client = Client.create(configureClient());
WebResource webResource = client.resource("https://server/endpoint/");
ClientResponse response = webResource.accept("application/json").get(ClientResponse.class);
if (response.getStatus() != 200) {
throw new RuntimeException("Failed : HTTP error code : " + response.getStatus());
}
List<Hardware> output = response.getEntity(new GenericType<List<Hardware>>() {});
LOG.severe("Output from Server .... \n");
LOG.severe("Nr of entries: " + output.size());
} catch (Exception e) {
LOG.log(Level.SEVERE, " test request failed", e);
}
}
public static ClientConfig configureClient() {
TrustManager[ ] certs = new TrustManager[ ] {
new X509TrustManager() {
#Override
public X509Certificate[] getAcceptedIssuers() {
LOG.severe("getAcceptedIssuers");
return null;
}
#Override
public void checkServerTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
LOG.severe("checkServerTrusted");
}
#Override
public void checkClientTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
LOG.severe("checkClientTrusted");
}
}
};
SSLContext ctx = null;
try {
ctx = SSLContext.getInstance("TLS");
ctx.init(null, certs, null);
} catch (java.security.GeneralSecurityException e) {
LOG.log(Level.SEVERE, "Error", e);
}
HttpsURLConnection.setDefaultSSLSocketFactory(ctx.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
#Override
public boolean verify(String hostname, SSLSession session) {
LOG.severe("verify");
return true;
}
});
ClientConfig config = new DefaultClientConfig();
try {
config.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES, new HTTPSProperties(
new HostnameVerifier() {
#Override
public boolean verify(String hostname, SSLSession session) {
LOG.severe("verify");
return true;
}
},
ctx
));
} catch(Exception e) {
LOG.log(Level.SEVERE, "Error", e);
}
return config;
}
}
While everything seems right, the log lines in the TrustManager and in the HostnameVerifier never show up in the logs, and the connection still failes with an SSL Handshaking Exception on the get(ClientResponse.class).
I've been going over this for a while now and when I compare this to all the tutorials and people saying they fixed it, I can't find a difference.
If someone could point out the flaw that should be in there somehwere....
My company BITPlan has published an open source project to simplify handling of Jersey 1.19 see
https://github.com/BITPlan/com.bitplan.simplerest
The test case:
https://github.com/BITPlan/com.bitplan.simplerest/blob/master/src/test/java/com/bitplan/rest/test/TestBasicAuth.java
creates an SSL connection with no client certificate being used.
This leads to:
Schwerwiegend: SSL Client certificate is missing for /hello/hello
but the testcase nevertheless runs
The handling on the Clientside is done with:
https://github.com/BITPlan/com.bitplan.simplerest/blob/master/src/main/java/com/bitplan/rest/SSLClientHelper.java
if you should have any trouble with this you might want to file an issue
via https://github.com/BITPlan/com.bitplan.simplerest/issues
Related
I am trying to connect to websocket server endpoint using below code but I am not able to resolve container.connectToServer(this, cec, uri); this. This method is not able to take my class as Endpoint class. It's a spring boot project. If I don't pass config then it accepts but then it fails to connect to server and return 401. I have tried many online links but failed to resolve this issue. Need help in how to fix it.
#ClientEndpoint
public class TestClassEndpoint {
private Session userSession = null;
public TestClassEndpoint(URI uri) {
try {
WebSocketContainer container = ContainerProvider.getWebSocketContainer();
ClientEndpointConfig cec = ClientEndpointConfig.Builder
.create().configurator(new ClientEndpointConfig.Configurator() {
public void beforeRequest(Map<String, List<String>> headers) {
System.out.println("Setting user cookie in beforeRequest ...");
headers.put("Authorization", Arrays.asList("Basic base64encodedString"));
}
}).build();
container.connectToServer(this, cec, uri);
} catch (Exception e) {
e.printStackTrace();
}
}
#OnOpen
public void onOpen(Session session) {
this.userSession = session;
System.out.println("New connection established");
}
#OnMessage
public void onMessage(String message, Session session) {
System.out.println(message);
}
#OnClose
public void onClose(Session userSession, CloseReason reason) {
this.userSession = null;
System.out.println("connection closed");
}
#OnError
public void onError(Throwable t) {
}
private void sendMessage(ByteBuffer buffer) {
this.userSession.getAsyncRemote().sendBinary(buffer);
}
}
Main class
#SpringBootApplication
public class MainApplication implements CommandLineRunner {
public static void main(String[] args) {
SpringApplication.run(TwilioPocApplication.class, args);
}
#Override
public void run(String... args) throws Exception {
URI uri = UriComponentsBuilder.fromUriString("server_url").build().toUri();
new TestClassEndpoint(uri);
}
}
I'm using a library that uses a Proxy on http requests to add security. The problem is that it works perfectly on Android >= KitKat, but in JellyBean it does not go through the proxy.
Do you know if proxy is supported using AndroidClientHandler in that version? I know that TLS 1.2+ is not supported using AndroidClientHandler pre Lollipop, but I need that handler (in fact I inherit from AndroidClientHandler to bypass SSL verification because the proxy takes care of that and it is needed by the library) to configure some things of how the proxy works.
MyCustomMessageHandler implementation:
public class MyCustomMessageHandler : AndroidClientHandler
{
public override bool SupportsProxy => true;
protected override SSLSocketFactory ConfigureCustomSSLSocketFactory(HttpsURLConnection connection)
{
return this.GetBypassVerificationSSLSocketFactory();
}
protected override IHostnameVerifier GetSSLHostnameVerifier(HttpsURLConnection connection)
{
return new CustomHostnameVerifier();
}
protected override async Task SetupRequest(HttpRequestMessage request, HttpURLConnection conn)
{
this.HandleCustomPreAuthentication(conn);
await base.SetupRequest(request, conn);
}
private void HandleCustomPreAuthentication(HttpURLConnection conn)
{
var proxyAuth = "MyUsername" + ":" + "MyPassword";
var encodedProxyAuth = Base64.EncodeToString(Encoding.UTF8.GetBytes(proxyAuth), Base64Flags.Default);
conn.SetRequestProperty("Proxy-Authorization", encodedProxyAuth);
}
private SSLSocketFactory GetBypassVerificationSSLSocketFactory()
{
SSLContext sslContext;
try
{
sslContext = SSLContext.GetInstance("SSL");
sslContext.Init(new IKeyManager[0], new ITrustManager[] { new X509TrustManager() }, new SecureRandom());
return sslContext.SocketFactory;
}
catch (GeneralSecurityException e)
{
throw new RuntimeException(e);
}
}
}
public class CustomHostnameVerifier : Java.Lang.Object, IHostnameVerifier
{
public bool Verify(string hostname, ISSLSession session) => true;
}
public class X509TrustManager : Java.Lang.Object, IX509TrustManager
{
public void CheckClientTrusted(X509Certificate[] chain, string authType)
{
}
public void CheckServerTrusted(X509Certificate[] chain, string authType)
{
}
public X509Certificate[] GetAcceptedIssuers()
{
return new X509Certificate[0];
}
}
I've already tried configuring the proxy using Managed client but it does not work as expected; that's why I chose AndroidClientHandler
I infer it is not going through the proxy because capturing packets I realized that < KitKat it sends the requests over Http while >= KitKat they are all over TCP or TLSv1.2 and the proxy is an https url.
Writing JUnit Integrtaion tests for a REST endpoint which sets secure cookies, can't get past the ResourceAccessException error.
Requirement is to do a https://localhost:8443 request.
Have tried using the customRestTemplate
Getting the folloiwng exception.
org.springframework.web.client.ResourceAccessException: I/O error on GET request for "https://localhost:8443/dcs": Connect to localhost:8443 [localhost/127.0.0.1, localhost/0:0:0:0:0:0:0:1] failed: Connection refused: connect; nested exception is org.apache.http.conn.HttpHostConnectException
Below is the code.
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class DcsServiceTests {
#Autowired
RestTemplateBuilder restTemplateBuilder;
#Autowired
private TestRestTemplate testRestTemplate;
#Test
public void testGet_ImageResponse() throws Exception {
//Arrange
//Act
ResponseEntity<byte[]> response = testRestTemplate.getForEntity(url, byte[].class);
//Assert
//Response Status
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
//Response has cookie
assertThat(response.getHeaders().containsKey("Set-Cookie")).isTrue();
}
#PostConstruct
public void initialize() {
// Lambda expression not working, TBD - Java version used.
//TrustStrategy acceptingTrustStrategy = (X509Certificate[] chain, String authType) -> true;
final TrustStrategy acceptingTrustStrategy = new TrustStrategy() {
#Override
public boolean isTrusted(java.security.cert.X509Certificate[] arg0, String arg1)
throws CertificateException {
return true;
}
};
HttpComponentsClientHttpRequestFactory requestFactory =
new HttpComponentsClientHttpRequestFactory();
try {
SSLContext sslContext = org.apache.http.ssl.SSLContexts.custom()
.loadTrustMaterial(null, acceptingTrustStrategy)
.build();
SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext);
CloseableHttpClient httpClient = HttpClients.custom()
.setSSLSocketFactory(csf)
.build();
requestFactory.setHttpClient(httpClient);
}
catch (Exception e) {
System.out.println("Exception occured creating Request Factory");
}
RestTemplate customTemplate = restTemplateBuilder
.requestFactory(requestFactory)
.rootUri("https://localhost:8443")
.build();
this.testRestTemplate = new TestRestTemplate(
customTemplate,
null,
null, // Not using basic auth
TestRestTemplate.HttpClientOption.ENABLE_COOKIES); // Cookie support
}
}
Disabling SSL and then using testRestTemplate with exchange method worked. Secured cookies works as well, just that the headers needs to be parsed to validate results in Unit test cases
#Bean
public Boolean disableSSLValidation() throws Exception {
final SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[] { new 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];
}
} }, null);
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
return true;
}
public void hostNameVerifier() {
final HostnameVerifier defaultHostnameVerifier = javax.net.ssl.HttpsURLConnection.getDefaultHostnameVerifier ();
final HostnameVerifier localhostAcceptedHostnameVerifier = new javax.net.ssl.HostnameVerifier () {
public boolean verify ( String hostname, javax.net.ssl.SSLSession sslSession ) {
if ( hostname.equals ( "localhost" ) ) {
return true;
}
return defaultHostnameVerifier.verify ( hostname, sslSession );
}
};
javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier ( localhostAcceptedHostnameVerifier );
}
#Test
public void testGet_ImageResponse() throws Exception {
//Arrange
String url = getUrl() + "/xyz?s_action=test&s_type=i";
//Act
ResponseEntity<byte[]> response = restTemplate.getForEntity(url, byte[].class);
//Assert
//Response Status
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
//Response has cookie
assertThat(response.getHeaders().containsKey("Set-Cookie")).isTrue();
//Extract cookie from header
List<String> cookies = response.getHeaders().get("Set-Cookie");
//Construct cookie from RAW Header Response
Cookie cookie = RawCookieParser.constructCookieFromHeaderResponse(response.getHeaders().get("Set-Cookie").toString());
//Cookies name matches
//Cookie value cannot be matched because value is being set from external JAR
assertEquals(cookie.getName(), appConfig.getName());
//Cookie domain matches
assertEquals(cookie.getDomain(), appConfig.getDomain());
}
public class RawCookieParser {
/*
* Construct a cookie object by parsing the HTTP Header response
*/
public static Cookie constructCookieFromHeaderResponse(String input) throws Exception {
String rawCookie = input.replace("[", "").replace("]", "");
String[] rawCookieParams = rawCookie.split(";");
String[] rawCookieNameAndValue = rawCookieParams[0].split("=");
if (rawCookieNameAndValue.length != 2) {
throw new Exception("Invalid cookie: missing name and value.");
}
String cookieName = rawCookieNameAndValue[0].trim();
String cookieValue = rawCookieNameAndValue[1].trim();
Cookie cookie = new Cookie(cookieName, cookieValue);
for (int i = 1; i < rawCookieParams.length; i++) {
String rawCookieParamNameAndValue[] = rawCookieParams[i].trim().split("=");
String paramName = rawCookieParamNameAndValue[0].trim();
if (rawCookieParamNameAndValue.length == 2) {
String paramValue = rawCookieParamNameAndValue[1].trim();
if (paramName.equalsIgnoreCase("secure")) {
cookie.setSecure(true);
} else if (paramName.equalsIgnoreCase("max-age")) {
int maxAge = Integer.parseInt(paramValue);
cookie.setMaxAge(maxAge);
} else if (paramName.equalsIgnoreCase("domain")) {
cookie.setDomain(paramValue);
} else if (paramName.equalsIgnoreCase("path")) {
cookie.setPath(paramValue);
}
}
}
return cookie;
}
}
I am Spring MVC beginner and I want to call rest in #ResponseBody. My external node server doesn't react on that method. I don't got message about request in my server console. Without UserRest it works. I would be grateful for your help
#Controller
public class AjaxController {
#RequestMapping(value= "user", method=RequestMethod.GET)
public #ResponseBody String login (){
UserRest ur = new UserRest();
Response r = ur.getUserName(2);
Gson gs = new Gson();
String str = gs.toJson(r);
return str;
}
}
Response getUserName(int userID){
Response response = new Response();
StringBuilder total = new StringBuilder();
try {
URL url = new URL(Properties.SERVER_SECURE_URL + "users/" + userID);
urlConnection = (HttpsURLConnection) url.openConnection();
urlConnection.setDoOutput(false);
urlConnection.setDoInput(true);
urlConnection.setRequestMethod("GET");
urlConnection.setRequestProperty("Authorization","1Strajk");
response.setMessageCode(urlConnection.getResponseCode());
if(response.getMessageCode()==Response.MESSAGE_OK) {
InputStream in = urlConnection.getInputStream();
BufferedReader r = new BufferedReader(new InputStreamReader(in));
String line;
while ((line = r.readLine()) != null) {
total.append(line);
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if(!total.toString().isEmpty()){
response.setObject(total.toString());
}
urlConnection.disconnect();
}
return response;
}
I resolve it. I forgot about SSL connection. Before calling rest I called that method:
public class SSLUtils {
public static void trustEveryone() {
try {
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, new X509TrustManager[]{new X509TrustManager(){
public void checkClientTrusted(X509Certificate[] chain,
String authType) throws CertificateException {}
public void checkServerTrusted(X509Certificate[] chain,
String authType) throws CertificateException {}
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}}}, new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(
context.getSocketFactory());
} catch (Exception e) { // should never happen
e.printStackTrace();
}
}
}
I am trying to connect to a REST API in an application deployed on weblogic 10.3.6. The sample code works fine when run independently (outside weblogic server). But when I deploy the same code it starts giving me this error
Failed to communicate with proxy: proxy.xxx.xxx/xxxx. Will try connection api.forecast.io/443 now.
weblogic.net.http.HttpUnauthorizedException: Proxy or Server Authentication Required
at weblogic.net.http.HttpURLConnection.getAuthInfo(HttpURLConnection.java:297)
at weblogic.net.http.HttpsClient.makeConnectionUsingProxy(HttpsClient.java:440)
at weblogic.net.http.HttpsClient.openServer(HttpsClient.java:351)
at weblogic.net.http.HttpsClient.New(HttpsClient.java:527)
at weblogic.net.http.HttpsURLConnection.connect(HttpsURLConnection.java:239)
Code that we are running is as below
try {
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, new X509TrustManager[] { new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] chain,
String authType) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain,
String authType) throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
} }, new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory());
} catch (Exception e) { // should never happen
e.printStackTrace();
}
try {
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("proxy.xxxx.xxxx", xxxx));
URL url = new URL("https://api.forecast.io/forecast/xxxxxxxxx/12.9667,77.5667");
HttpURLConnection conn = (HttpURLConnection)url.openConnection(proxy);
conn.setRequestMethod("GET");
conn.setRequestProperty("Accept", "application/json");
if (conn.getResponseCode() != 200) {
throw new RuntimeException("Failed : HTTP error code : " + conn.getResponseCode());
}
BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream())));
String output;
System.out.println("Output from Server .... \n");
while ((output = br.readLine()) != null) {
System.out.println(output);
}
conn.disconnect();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return "";
Our proxy is a company proxy and doesn't have any username/password. We are stuck on this issue for sometime now. Any suggestions/pointers will be really appreciated.