My question is that do i have to make a separate request to check SSL Pinning before every Get/Post Request
OkHttpClient client = new OkHttpClient.Builder().certificatePinner(
new CertificatePinner.Builder()
.add(pinningUrl, "sha256/invalidPIN")
.build()).build();
Request request = new Request.Builder()
.url(pinningUrl)
.build();
Response response = client.newCall(request).execute();
Or can i check it with every Get/Post like this
CertificatePinner certificatePinner = new CertificatePinner.Builder()
.add(pinningUrl, "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=") .build();
OkHttpClient client = new OkHttpClient().newBuilder().certificatePinner(certificatePinner).build();
Request request = new Request.Builder() .url(getResources().getString(R.string.server_url_user_mgmt_services))
.addHeader("Content-Type", "application).post(body)
.build();
client.newCall(request)
.enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
pd.dismiss();
Toast.makeText(LoginActivity.this, "Some error occured!\nTry Again", Toast.LENGTH_SHORT).show();
}
#Override
public void onResponse(Call call, Response response) throws IOException {
String str = response.body().toString();
}
});
If i check it on every request the request is executed but it does not check for certificate help me with this.
Based on your first code example it looks like you are trying to pin with a URL instead of a hostname or wildcard.
You should configure it once on your OkHttpClient per host and then just make your normal requests. The pins you define should have the host as the key, not the url.
https://square.github.io/okhttp/3.x/okhttp/okhttp3/CertificatePinner.html
String hostname = "publicobject.com";
CertificatePinner certificatePinner = new CertificatePinner.Builder()
.add(hostname, "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=")
.build();
OkHttpClient client = OkHttpClient.Builder()
.certificatePinner(certificatePinner)
.build();
Request request = new Request.Builder()
.url("https://" + hostname)
.build();
client.newCall(request).execute();
Related
I have a singleton instance of http client and will setting the retry count for every request on execute. Is there a solution?
i only found to set the DefaultHttpRequestRetryHandler globaly in the httpClientBuilder.
httpClientBuilder.setRetryHandler(new DefaultHttpRequestRetryHandler(10, false));
but this is for all request identical (10)
One can always a custom context attribute to customize HttpClient behavior
CloseableHttpClient httpClient = HttpClientBuilder.create()
.setRetryHandler((exception, executionCount, context) -> executionCount < (Integer) context.getAttribute("retry.count"))
.build();
HttpClientContext clientContext = HttpClientContext.create();
clientContext.setAttribute("retry.count", 4);
HttpGet get1 = new HttpGet("http://host/");
try (CloseableHttpResponse response1 = httpClient.execute(get1)) {
EntityUtils.consume(response1.getEntity());
}
clientContext.setAttribute("retry.count", 10);
HttpGet get2 = new HttpGet("http://host/");
try (CloseableHttpResponse response2 = httpClient.execute(get2)) {
EntityUtils.consume(response2.getEntity());
}
private void setUpRestClient() {
OkHttpClient client = new OkHttpClient();
client.interceptors().add(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Request original = chain.request();
Request request = original.newBuilder()
.header("Accept", "application/pyur.v1")
.header("Authorization", new SharedPreferencesUtil(getBaseContext()).getToken())
.header("Content-Type", "application/json")
.method(original.method(),original.body())
.build();
return chain.proceed(request);
}
});
RestClient.getInstance().configureRestAdapter(this, getResources().getString(R.string.base_url),client);
}
public void configureRestAdapter(final Context context, String baseUrl, OkHttpClient client) {
Gson gson = new GsonBuilder()
.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
.setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
.excludeFieldsWithModifiers(Modifier.FINAL, Modifier.TRANSIENT, Modifier.STATIC)
.create();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create(gson))
.client(client)
.build();
service = retrofit.create(NetworkServiceInterface.class);
}
This now gives me a failure return in Retrofit 2.0, originally I had it without the "Authorization" header and it was giving me unauthorized, which is understandable. But now I'm authorizing it with my auth token and it fails. New to Retrofit 2.0, thanks --
You can pass Authorization Header as:
#GET("/v1/OrderReport.json")
Call<POJO_Class> getExampleMethod(#Header("Authorization") String token, #Query("id") String id);
and then call as:
getExampleMethod("Basic " + token, id);
You can add Authorization Header for every calls using Interceptor in Retrofit 2, by using the OkHttpClient.Builder class. Like this.
import okhttp3.OkHttpClient;
import okhttp3.Interceptor;
OkHttpClient defaultHttpClient = new OkHttpClient.Builder()
.addInterceptor(new Interceptor() {
#Override
public Response intercept(Interceptor.Chain chain) throws IOException {
//getAccessToken is your own accessToken(retrieve it by saving in shared preference or any other option )
if(getAccessToken().isEmpty()){
PrintLog.error("retrofit 2","Authorization header is already present or token is empty....");
return chain.proceed(chain.request());
}
Request authorisedRequest = chain.request().newBuilder()
.addHeader("Authorization", getAccessToken()).build();
PrintLog.error("retrofit 2","Authorization header is added to the url....");
return chain.proceed(authorisedRequest);
}}).build();
And add this client object to the retrofit object.
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL) //BaseURL always ends with "/"
.addConverterFactory(GsonConverterFactory.create())
.client(defaultHttpClient)
.build();
Now for every calls that you make using the retrofit object will add the "Authorization" header along with the url. And also we handle the condition that if the authorization value is empty, then we simply omit the Authorization header part for the request call.
From Retrofit:2.0
you have to use OkHttpClient.Builder() class to add Interceptors.
So you have to change your code like this.
OkHttpClient client = new OkHttpClient.Builder();
client.addInterceptor(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Request original = chain.request();
Request request = original.newBuilder()
.header("Accept", "application/pyur.v1")
.header("Authorization", new SharedPreferencesUtil(getBaseContext()).getToken())
.header("Content-Type", "application/json")
.method(original.method(),original.body())
.build();
return chain.proceed(request);
}
}).build();
I am trying to build a Junit/Integration test which needs to contact an external server. However, I cannot get past the proxy. I get a 407 blank authentication page error.
The Test setup I use
#Before
public void onSetUp() throws Exception {
System.setProperty("http.proxyHost", "webproxy-nl.test.com");
System.setProperty("http.proxyPort", "8080");
System.setProperty("https.proxyHost", "webproxy-nl.test.com");
System.setProperty("https.proxyPort", "8080");
System.setProperty("http.proxyUser", "DOM\\lalal");
System.setProperty("http.proxyPassword", "tesssst");
System.setProperty("https.proxyUser", "DOM\\lalala");
System.setProperty("https.proxyPassword", "sldjsdkl");
}
Now all proxy settings are 100% correct. I added some nonProxyhosts as well.
I do not know what else I could configure here.
The return message is:
Http request failed: HTTP/1.1 407 BlankAuthenticationPage [status code 407]
UPDATE
I built a test stub which uses the CloseableHttpClient. This still gives me the http 407 error.
private CloseableHttpClient httpClient;
public IDealHttpClientStub() {
LOG.debug("Creating IDealHttpClientStub");
System.setProperty("http.proxyHost", "webproxy-nl.test.com");
System.setProperty("http.proxyPort", "8080");
System.setProperty("https.proxyHost", "webproxy-nl.test.com");
System.setProperty("https.proxyPort", "8080");
System.setProperty("http.proxyUser", "DOM\\lalal");
System.setProperty("http.proxyPassword", "tesssst");
System.setProperty("https.proxyUser", "DOM\\lalala");
System.setProperty("https.proxyPassword", "sldjsdkl");
this.httpClient = HttpClients.custom().useSystemProperties().build();
}
HttpClient does not make use of system properties unless explicitly configured to do so.
CloseableHttpClient client1 = HttpClients.createSystem();
CloseableHttpClient client2 = HttpClients.custom()
.useSystemProperties()
.build();
I have done it using the following impl.
private CloseableHttpClient httpClient;
public HttpClientStub() throws KeyManagementException, NoSuchAlgorithmException, KeyStoreException {
// Trust all certs
SSLContext sslcontext = buildSSLContext();
// Allow TLSv1 protocol only
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[] { "TLSv1" }, null,
SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
HttpHost proxy = new HttpHost("someproxy", 8080, "http");
DefaultProxyRoutePlanner routePlanner = new DefaultProxyRoutePlanner(proxy);
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(
new AuthScope("someproxy", 8080, AuthScope.ANY_HOST, "ntlm"), new NTCredentials(
"itsme", "xxxx", "", "MYDOMAIN"));
this.httpClient = HttpClients.custom().setDefaultCredentialsProvider(credsProvider)
.setRoutePlanner(routePlanner).setSSLSocketFactory(sslsf).build();
}
private static SSLContext buildSSLContext() throws NoSuchAlgorithmException, KeyManagementException,
KeyStoreException {
SSLContext sslcontext = SSLContexts.custom().setSecureRandom(new SecureRandom())
.loadTrustMaterial(null, new TrustStrategy() {
#Override
public boolean isTrusted(java.security.cert.X509Certificate[] chain, String authType)
throws java.security.cert.CertificateException {
return true;
}
}).build();
return sslcontext;
}
Then you have your proxy configured HTTP (Test) client.
I am trying to get some data from webserver which works fine with http.
But when I try https(ssl connection), I get the exceptions like below.
I get the http status code 200 and response content length 2230 which is correct.
java.net.SocketException: Socket is closed
at sun.security.ssl.SSLSocketImpl.checkEOF(SSLSocketImpl.java:1483)
at sun.security.ssl.AppInputStream.read(AppInputStream.java:92)
at org.apache.http.impl.io.AbstractSessionInputBuffer.fillBuffer(AbstractSessionInputBuffer.java:166)
at org.apache.http.impl.io.SocketInputBuffer.fillBuffer(SocketInputBuffer.java:90)
at org.apache.http.impl.io.AbstractSessionInputBuffer.read(AbstractSessionInputBuffer.java:183)
at org.apache.http.impl.io.ContentLengthInputStream.read(ContentLengthInputStream.java:144)
at org.apache.http.conn.EofSensorInputStream.read(EofSensorInputStream.java:121)
My code is like below with apache httpcomponents httpclient(4.2.5) library.
try {
HttpPost httppost = new HttpPost(uri);
HttpHost targetHost = new HttpHost(HOST_NAME, HOST_PORT, PROTOCOL);
InputStreamEntity reqEntity = new InputStreamEntity(new ByteArrayInputStream(request), -1);
String contentType = TSPConstants.CONST_TSA_CONTENT_TYPE_TSREQUEST;
reqEntity.setContentType(contentType);
reqEntity.setChunked(true);
// It may be more appropriate to use FileEntity class in this particular
// instance but we are using a more generic InputStreamEntity to demonstrate
// the capability to stream out data from any arbitrary source
//
// FileEntity entity = new FileEntity(file, "binary/octet-stream");
httppost.setEntity(reqEntity);
//Authentication
httpclient.getCredentialsProvider().setCredentials(
new AuthScope(targetHost.getHostName(), targetHost.getPort()),
new UsernamePasswordCredentials(id, password));
// Create AuthCache instance
AuthCache authCache = new BasicAuthCache();
// Generate BASIC scheme object and add it to the local
// auth cache
BasicScheme basicAuth = new BasicScheme();
authCache.put(targetHost, basicAuth);
// Add AuthCache to the execution context
BasicHttpContext httpContext = new BasicHttpContext();
httpContext.setAttribute(ClientContext.AUTH_CACHE, authCache);
httpContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
//SSL
SSLContext ctx = SSLContext.getInstance("TLS");
X509TrustManager tm = new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException { }
public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException { }
public X509Certificate[] getAcceptedIssuers() {
return null;
}
};
ctx.init(null, new TrustManager[]{tm}, null);
SSLSocketFactory ssf = new SSLSocketFactory(ctx, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
Scheme sch = new Scheme("https", HOST_PORT, ssf);
httpclient.getConnectionManager().getSchemeRegistry().register(sch);
System.out.println("executing request " + httppost.getRequestLine());
httpclient.execute(httppost, httpContext);
HttpResponse response = send(request);
HttpEntity resEntity = response.getEntity();
System.out.println("----------------------------------------");
System.out.println(response.getStatusLine());
if (resEntity != null) {
System.out.println("Response content length: " + resEntity.getContentLength());
System.out.println("Chunked?: " + resEntity.isChunked());
}
EntityUtils.consume(resEntity);
resEntity.getContent()
} finally {
// When HttpClient instance is no longer needed,
// shut down the connection manager to ensure
// immediate deallocation of all system resources
httpclient.getConnectionManager().shutdown();
}
Basically the answer gave #Avner in the comment.
The problem (for me) was, that the response was closed before the entity was read.
I did something like this, which was wrong:
HttpEntity entity = null;
try (CloseableHttpResponse response = client.execute(request)) {
entity = response.getEntity();
}
read(entity);
The following worked:
try (CloseableHttpResponse response = client.execute(request)) {
HttpEntity entity = response.getEntity();
read(entity);
}
The maybe not so obvious part: The try-with-resources block in the first example closed the stream, before it was read.
I am not able to authenticate in stripe.com - using Basic Authentication
public class Str extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
PrintWriter pw=response.getWriter();
pw.println("Hello World");
HttpClient client= new HttpClient();
String req="https://api.stripe.com/";
client.getParams().setAuthenticationPreemptive(true);
client.getState().setCredentials(new AuthScope(req, 443, null), new UsernamePasswordCredentials("<api-key>"));
client.getHostConfiguration().setHost(req, 443, "https");
PostMethod post= new PostMethod("https://api.stripe.com/v1/charges/");
//post.addParameter("id", "<id>");
int status=client.executeMethod(post);
pw.println(status);
}
}
i am presenting my code...where i hv used HTTP Basic Auth to provide the users credentials to stripe.com
Try: new UsernamePasswordCredentials("<api-key>", "")
Hope this will help you.
Here API_KEY means secrete key
HttpResponse httpResponse;
String request ='card[number]='+card_name+'&card[exp_year]='+card_exp_year+'&card[exp_month]='+card_exp_month+'&card[cvc]='+card_cvv+'&amount='+amount+ '¤cy='+currency;
Http httpObject = new Http();
HttpRequest httpRequest = new HttpRequest();
httpRequest.setEndpoint(sHttpEndPoint);
httpRequest.setMethod('POST');
Blob headerValue = Blob.valueOf(API_KEY + ':');
String authorizationHeader = 'BASIC ' +
EncodingUtil.base64Encode(headerValue);
httpRequest.setHeader('Authorization', authorizationHeader);
httpRequest.setBody(request);
httpResponse = httpObject.send(httpRequest);