I am using okhttp3 and trying to see how do I pass userId & pswd to authenticate with proxy server that accepts only HTTPS protocol. I already saw exmaple over SO & on other sites(link below) but they don't have HTTPS protocol.
https://botproxy.net/docs/how-to/okhttpclient-proxy-authentication-how-to/
Can anyone please tell me how to use HTTPS protocol to call proxy server?
It is not officially supported but there is a workaround.
https://github.com/square/okhttp/issues/6561
Authenticator proxyAuthenticator = new Authenticator() {
#Override public Request authenticate(Route route, Response response) throws IOException {
String credential = Credentials.basic(username, password);
return response.request().newBuilder().header("Proxy-Authorization", credential).build();
}
};
OkHttpClient client = new OkHttpClient.Builder()
.proxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, proxyPort)))
.proxyAuthenticator(proxyAuthenticator);
.socketFactory(new DelegatingSocketFactory(SSLSocketFactory.getDefault()))
.build();
Related
I am using the latest version of JDK8
My CloseableHttpAsyncClient is created by doing the following
try{
sslContext = SSLContexts.custom()
.setProvider(Conscrypt.newProvider())
.build();
}catch (Exception e){
e.printStackTrace();
}
final PoolingAsyncClientConnectionManager cm = PoolingAsyncClientConnectionManagerBuilder.create()
.setTlsStrategy(new ConscryptClientTlsStrategy(sslContext))
.build();
BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
if (proxy.isAuth()) {
credentialsProvider.setCredentials(
new AuthScope(proxy.getIp(), Integer.parseInt(proxy.getPort())),
new UsernamePasswordCredentials(proxy.getUsername(), proxy.getPassword().toCharArray()));
}
HttpHost p = new HttpHost(proxy.getIp(), Integer.parseInt(proxy.getPort()), "http");
asyncClient = HttpAsyncClients.custom()
.setVersionPolicy(HttpVersionPolicy.FORCE_HTTP_1)
.setConnectionManager(cm)
.setUserAgent(Utils.USER_AGENT)
.setDefaultCookieStore(cookieStore)
.setDefaultCredentialsProvider(credentialsProvider)
.setProxy(p)
.build();
asyncClient.start();
I am then trying to do a post request which works without a proxy. The request with the proxy also works with the url using http and not https. I receive the following error java.lang.IllegalStateException: No tunnel unless connected when using https and a proxy.
I'm trying to use JDK 11 HttpClient to make requests through a corporate proxy which requires authentication by login and password. According to JDK's intro, I'm building an instance of client by means of:
HttpClient httpClient = HttpClient.newBuilder()
.version(HTTP_1_1)
.proxy(ProxySelector.of(new InetSocketAddress("proxy.mycompany.com", 3128)))
.authenticator(authenticator)
.build();
, where authenticator is:
Authenticator authenticator = new Authenticator() {
#Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("login", "password".toCharArray());
}
};
And then I execute the request itself:
HttpRequest outRequest = HttpRequest.newBuilder()
.version(HTTP_1_1)
.GET()
.uri(URI.create("https://httpwg.org/asset/http.svg")) // no matter which URI to request
.build();
HttpResponse<String> inResponse = httpClient.send(outRequest, BodyHandlers.ofString());
But instead of valid response from the target server (https://httpwg.org) I receive HTTP 407 (Proxy Authentication Required), i.e. HttpClient does not use the provided authenticator.
I've tried various solutions mentioned here and here but none of them helped.
What is the correct way to make it work?
You have to set the "Proxy-Authorization" header on the request.
HttpClient httpClient = HttpClient.newBuilder()
.version(HTTP_1_1)
.proxy(ProxySelector.of(new InetSocketAddress("proxy.mycompany.com", 3128)))
.build();
String encoded = new String(Base64.getEncoder().encode("login:password".getBytes()));
HttpRequest outRequest = HttpRequest.newBuilder()
.version(HTTP_1_1)
.GET()
.uri(URI.create("https://httpwg.org/asset/http.svg")) // no matter which URI to request
.setHeader("Proxy-Authorization", "Basic " + encoded)
.build();
By default, basic authentication with the proxy is disabled when tunneling through an authenticating proxy since java 8u111.
You can re-enable it by specifying -Djdk.http.auth.tunneling.disabledSchemes="" on the java command line.
See the jdk 8u111 release notes
Use
System.setProperty("jdk.http.auth.proxying.disabledSchemes", "");
System.setProperty("jdk.http.auth.tunneling.disabledSchemes", "");
Construct your http client with proxy selector and authenticator
HttpClient client = HttpClient.newBuilder()
.authenticator(yourCustomAuthenticator)
.proxy(yourCustomProxySelector)
.build();
In your Authenticator override
#Override
protected PasswordAuthentication getPasswordAuthentication() {
if (getRequestorType().equals(RequestorType.PROXY)) {
return getPasswordAuthentication(getRequestingHost());
} else {
return null;
}
}
protected PasswordAuthentication getPasswordAuthentication(String proxyHost) {
// your logic to find username and password for proxyHost
return new PasswordAuthentication(proxyUsername, proxyPassword.toCharArray());
// or return null
}
How can I use Socks5 proxy in Okhttp to start http request ?
My code:
Proxy proxy = new Proxy(Proxy.Type.SOCKS, InetSocketAddress.createUnresolved(
"socks5host", 80));
OkHttpClient client = new OkHttpClient.Builder()
.proxy(proxy).authenticator(new Authenticator() {
#Override
public Request authenticate(Route route, Response response) throws IOException {
if (HttpUtils.responseCount(response) >= 3) {
return null;
}
String credential = Credentials.basic("user", "psw");
if (credential.equals(response.request().header("Authorization"))) {
return null; // If we already failed with these credentials, don't retry.
}
return response.request().newBuilder().header("Authorization", credential).build();
}
}).build();
Request request = new Request.Builder().url("http://google.com").get().build();
Response response = client.newCall(request).execute(); <--- **Here, always throw java.net.UnknownHostException: Host is unresolved: google.com**
System.out.println(response.body().string());
How to avoid UnknownHostException?
Any example ?
Thanks!
I found a solution: When create a OkHttpClient.Builder(), set a new socketFactory instead of set proxy, and return a sock5 proxy inside socketFactory createSocket.
I think it's the easiest working soulution. But it seems to me that it can be not 100% safe. I took this code from this code from here and modified it because my proxy's RequestorType is SERVER.
Actually, java has a strange api for proxies, you should to set auth for proxy through system env ( you can see it from the same link)
final int proxyPort = 1080; //your proxy port
final String proxyHost = "your proxy host";
final String username = "proxy username";
final String password = "proxy password";
InetSocketAddress proxyAddr = new InetSocketAddress(proxyHost, proxyPort);
Proxy proxy = new Proxy(Proxy.Type.SOCKS, proxyAddr);
Authenticator.setDefault(new Authenticator() {
#Override
protected PasswordAuthentication getPasswordAuthentication() {
if (getRequestingHost().equalsIgnoreCase(proxyHost)) {
if (proxyPort == getRequestingPort()) {
return new PasswordAuthentication(username, password.toCharArray());
}
}
return null;
}
});
OkHttpClient client = new OkHttpClient.Builder()
.proxy(proxy)
.build();
I have a linux\java6 client that will authenticate to sharepoint2010 with NTLM and then send HTTP REST web services using Apache Commons HttpClient.
I can do this with NTLM , but I want to use the same REST API to access sharepoint 2010 that uses kerberos auth.
Any examples how to authenticate and send REST over HTTP with a kerberos sharepoint?
(preferably using HttpClient)
p.s.
I dont have access to sharepoint code, but i do have access to sharepoint admin configurations.
This is roughly how I authenticate with NTLM:
HttpClient httpClient = new HttpClient(new SimpleHttpConnectionManager(true));
AuthPolicy.registerAuthScheme(AuthPolicy.NTLM, JCIFS_NTLMScheme.class);
String localHostName = Inet4Address.getLocalHost().getHostName();
authscope = new AuthScope(uri.getHost(), AuthScope.ANY_PORT);
httpClient.getState().setCredentials(authscope,new NTCredentials(
getUsername(),getPassword(),localHostName,getDomain()));
// after the initial ntlm auth I can call my REST service with "httpClient.executeMethod"
int status = httpClient.executeMethod(new GetMethod(accessURI + "/sitecollection/info"));
Please confirm that your environment is correctly setup for Kerberos, this can be achieved by running kinit. If this fails you will need to ensure that your krb5.ini (windows) or krb5.conf (linux) are setup to point to your domain controller correctly.
Once you have confirmed that Kerberos is functional you can use the example code from HttpClient as pasted below.
Please note that there are many issues that can cause Kerberos to fail, such as time synchronisation, supported encryption types, trust relationships across domain forests and it's also worth ensuring that your client is on a seperate box to the server.
Here is the example code which is available in the HttpClient download, you will need to ensure your JAAS configuration and krb5.conf or ini are correct!
public class ClientKerberosAuthentication {
public static void main(String[] args) throws Exception {
System.setProperty("java.security.auth.login.config", "login.conf");
System.setProperty("java.security.krb5.conf", "krb5.conf");
System.setProperty("sun.security.krb5.debug", "true");
System.setProperty("javax.security.auth.useSubjectCredsOnly","false");
DefaultHttpClient httpclient = new DefaultHttpClient();
try {
httpclient.getAuthSchemes().register(AuthPolicy.SPNEGO, new SPNegoSchemeFactory());
Credentials use_jaas_creds = new Credentials() {
public String getPassword() {
return null;
}
public Principal getUserPrincipal() {
return null;
}
};
httpclient.getCredentialsProvider().setCredentials(
new AuthScope(null, -1, null),
use_jaas_creds);
HttpUriRequest request = new HttpGet("http://kerberoshost/");
HttpResponse response = httpclient.execute(request);
HttpEntity entity = response.getEntity();
System.out.println("----------------------------------------");
System.out.println(response.getStatusLine());
System.out.println("----------------------------------------");
if (entity != null) {
System.out.println(EntityUtils.toString(entity));
}
System.out.println("----------------------------------------");
// This ensures the connection gets released back to the manager
EntityUtils.consume(entity);
} finally {
// When HttpClient instance is no longer needed,
// shut down the connection manager to ensure
// immediate deallocation of all system resources
httpclient.getConnectionManager().shutdown();
}
}
}
I am using jersey client with ApacheConnection Provider.
Builder builder = RequestConfig.custom().setConnectTimeout(timeout);
List<Proxy> proxies = ProxyManager.getInstance().select(baseUrl.toURI());
if (useProxy) {
...
builder.setProxy(new HttpHost(proxyUri.getHost(), proxyUri.getPort()));
}
RequestConfig requestConfig = builder.build();
final ClientConfig clientConfig = new ClientConfig();
clientConfig.property(ApacheClientProperties.REQUEST_CONFIG, requestConfig);
clientConfig.connectorProvider(new ApacheConnectorProvider());
client = ClientBuilder.newBuilder().withConfig(clientConfig).sslContext(getSSLContext()).build();
client.property(ClientProperties.CONNECT_TIMEOUT, 5000);
But how to add username and password for Proxy authentication?
Seems like apache connection provider does not use the standard java proxy selector mechanisms.
I finally found the solution by myself. Unfortunately this is documented nowhere:
HttpHost proxyhost = new HttpHost(host,pw);
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(new AuthScope(proxyhost), new UsernamePasswordCredentials(user, pw));
clientConfig.property(ApacheClientProperties.CREDENTIALS_PROVIDER, credsProvider);
builder.setProxy(proxyhost);
I think you should add few more lines of code
builder.setProxy(proxyhost).setDefaultCredentialsProvider(credsProvider)
.setProxyAuthenticationStrategy(new ProxyAuthenticationStrategy());
otherwise it wont really authenticate the proxy host I feel. In your case it might be bypassing the proxy. ?