先用Apache HttpClient 4进行基本身份validation

有没有一种更简单的方法来设置HTTP客户端抢先基本authentication比这里描述的?
在以前的版本(3.x)中,它曾经是一个简单的方法调用(例如, httpClient.getParams().setAuthenticationPreemptive(true) )。
我想避免的主要事情是将BasicHttpContext添加到我执行的每个方法。

每次都不传递上下文很难做到这一点,但可以通过使用请求拦截器来完成。 下面是我们使用的一些代码(从他们的JIRA,iirc中find):

 // Pre-emptive authentication to speed things up BasicHttpContext localContext = new BasicHttpContext(); BasicScheme basicAuth = new BasicScheme(); localContext.setAttribute("preemptive-auth", basicAuth); httpClient.addRequestInterceptor(new PreemptiveAuthInterceptor(), 0); (...) static class PreemptiveAuthInterceptor implements HttpRequestInterceptor { public void process(final HttpRequest request, final HttpContext context) throws HttpException, IOException { AuthState authState = (AuthState) context.getAttribute(ClientContext.TARGET_AUTH_STATE); // If no auth scheme avaialble yet, try to initialize it // preemptively if (authState.getAuthScheme() == null) { AuthScheme authScheme = (AuthScheme) context.getAttribute("preemptive-auth"); CredentialsProvider credsProvider = (CredentialsProvider) context.getAttribute(ClientContext.CREDS_PROVIDER); HttpHost targetHost = (HttpHost) context.getAttribute(ExecutionContext.HTTP_TARGET_HOST); if (authScheme != null) { Credentials creds = credsProvider.getCredentials(new AuthScope(targetHost.getHostName(), targetHost.getPort())); if (creds == null) { throw new HttpException("No credentials for preemptive authentication"); } authState.setAuthScheme(authScheme); authState.setCredentials(creds); } } } } 

如果您希望强制HttpClient 4使用单个请求进行身份validation,则以下操作将起作用:

 String username = ... String password = ... UsernamePasswordCredentials creds = new UsernamePasswordCredentials(username, password); HttpRequest request = ... request.addHeader(new BasicScheme().authenticate(creds, request)); 

这与Mat的Mannion的解决scheme是一样的,但是你不必把localContext放到每个请求中。 这很简单,但是它增加了所有请求的authentication。 有用的,如果你不能控制个别请求,就像我在使用内部使用HttpClient的Apache Solr时一样。

 import org.apache.http.HttpException; import org.apache.http.HttpHost; import org.apache.http.HttpRequest; import org.apache.http.HttpRequestInterceptor; import org.apache.http.auth.AuthScope; import org.apache.http.auth.AuthState; import org.apache.http.auth.Credentials; import org.apache.http.client.CredentialsProvider; import org.apache.http.client.protocol.ClientContext; import org.apache.http.impl.auth.BasicScheme; import org.apache.http.protocol.ExecutionContext; import org.apache.http.protocol.HttpContext; httpClient.addRequestInterceptor(new PreemptiveAuthInterceptor(), 0); (...) static class PreemptiveAuthInterceptor implements HttpRequestInterceptor { public void process(final HttpRequest request, final HttpContext context) throws HttpException, IOException { AuthState authState = (AuthState) context.getAttribute(ClientContext.TARGET_AUTH_STATE); // If no auth scheme available yet, try to initialize it // preemptively if (authState.getAuthScheme() == null) { CredentialsProvider credsProvider = (CredentialsProvider) context.getAttribute(ClientContext.CREDS_PROVIDER); HttpHost targetHost = (HttpHost) context.getAttribute(ExecutionContext.HTTP_TARGET_HOST); Credentials creds = credsProvider.getCredentials(new AuthScope(targetHost.getHostName(), targetHost.getPort())); if (creds == null) { throw new HttpException("No credentials for preemptive authentication"); } authState.setAuthScheme(new BasicScheme()); authState.setCredentials(creds); } } } 

当然,你必须设置凭证提供者:

 httpClient.getCredentialsProvider().setCredentials( new AuthScope(url.getHost(), url.getPort()), new UsernamePasswordCredentials(username, password)) 

AuthScope不能包含领域,因为事先不知道。

上面的许多答案使用了不推荐的代码。 我正在使用Apache SOLRJ版本5.0.0。 我的代码包含

 private HttpSolrClient solrClient; private void initialiseSOLRClient() { URL solrURL = null; try { solrURL = new URL(urlString); } catch (MalformedURLException e) { LOG.error("Cannot parse the SOLR URL!!" + urlString); throw new SystemException("Cannot parse the SOLR URL!! " + urlString, e); } String host = solrURL.getHost(); int port = solrURL.getPort(); AuthScope authScope = new AuthScope(host, port); BasicTextEncryptor textEncryptor = new BasicTextEncryptor(); textEncryptor.setPassword("red bananas in the spring"); String decryptPass = textEncryptor.decrypt(pass); UsernamePasswordCredentials creds = new UsernamePasswordCredentials(userName, decryptPass); CredentialsProvider credsProvider = new BasicCredentialsProvider(); credsProvider.setCredentials( authScope, creds); HttpClientBuilder builder = HttpClientBuilder.create(); builder.addInterceptorFirst(new PreemptiveAuthInterceptor()); builder.setDefaultCredentialsProvider(credsProvider); CloseableHttpClient httpClient = builder.build(); solrClient = new HttpSolrClient(urlString, httpClient); } 

PreemptiveAuthInterceptor现在如下所示:

 static class PreemptiveAuthInterceptor implements HttpRequestInterceptor { public void process(final HttpRequest request, final HttpContext context) throws HttpException, IOException { AuthState authState = (AuthState) context.getAttribute(HttpClientContext.TARGET_AUTH_STATE); // If no auth scheme available yet, try to initialize it // preemptively if (authState.getAuthScheme() == null) { CredentialsProvider credsProvider = (CredentialsProvider) context.getAttribute(HttpClientContext.CREDS_PROVIDER); HttpHost targetHost = (HttpHost) context.getAttribute(HttpCoreContext.HTTP_TARGET_HOST); AuthScope authScope = new AuthScope(targetHost.getHostName(), targetHost.getPort()); Credentials creds = credsProvider.getCredentials(authScope); if(creds == null){ } authState.update(new BasicScheme(), creds); } } } 

晚了一点晚了,但我来到这个线程试图解决这个代理预授权的发布请求。 为了增加亚当的回应,我发现以下工作适合我:

 HttpPost httppost = new HttpPost(url); UsernamePasswordCredentials creds = new UsernamePasswordCredentials(username, password); Header bs = new BasicScheme().authenticate(creds, httppost); httppost.addHeader("Proxy-Authorization", bs.getValue()); 

认为这可能会有助于任何人遇到这种情况。

我认为最好的办法可能是手动完成。 我添加了以下function

经典的Java:

 import javax.xml.bind.DatatypeConverter; 

 private static void addAuthHeader(HttpRequestBase http, String username, String password) throws UnsupportedEncodingException { String encoded = DatatypeConverter.printBase64Binary((username + ":" + password).getBytes("UTF-8")); http.addHeader("AUTHORIZATION", "Basic " + encoded); } 

HTTPRequestBase可以是HttpGetHttpPost一个实例

安卓:

 import android.util.Base64; 

 private static void addAuthHeader(HttpRequestBase http, String username, String password) throws UnsupportedEncodingException { String encoded = Base64.encodeToString((username + ":" + password).getBytes("UTF-8"), Base64.NO_WRAP); http.addHeader("AUTHORIZATION", "Basic " + encoded); } 

我使用这个代码,基于我的HTTPClient 4.5文档阅读:

 HttpClientContext ctx = HttpClientContext.create() ctx.setCredentialsProvider(new BasicCredentialsProvider()) ctx.setAuthCache(new BasicAuthCache()) UsernamePasswordCredentials creds = new UsernamePasswordCredentials(user, pass) AuthScope authScope = new AuthScope(host, port) ctx.getCredentialsProvider.setCredentials(authScope, credentials) // This part makes authentication preemptive: HttpHost targetHost = new HttpHost(host, port, scheme) ctx.getAuthCache.put(targetHost, new BasicScheme()) 

…并确保您始终将该上下文传递给HTTPClient.execute()

我不太了解你的结论。 HttpClient拥有所有的机制来进行抢先authentication,而且你只需要做一次(当你构build和configuration你的HttpClient的时候)。 一旦你完成了,你就像往常一样构造你的方法实例。 你不“添加BasicHttpContext”的方法。

我认为最好的办法就是拥有自己的对象来设置抢先validation所需的所有垃圾,并且有一个简单的方法来执行给定HTTPMethod对象上的请求。

在Android中,Mat Mannion的答案无法parsinghttps,仍然发送两个请求,你可以像下面这样做,诀窍是追加authHeader与用户代理:

  public static DefaultHttpClient createProxyHttpClient() { try { final DefaultHttpClient client = createPlaintHttpClient(); client.setRoutePlanner(new HttpRoutePlanner() { @Override public HttpRoute determineRoute(HttpHost target, HttpRequest request, HttpContext context) throws HttpException { boolean isSecure = "https".equalsIgnoreCase(target.getSchemeName()); if (needProxy) { Header header = isSecure ? ProxyUtils.createHttpsAuthHeader() : ProxyUtils.createAuthHeader(); if (isSecure) { client.getParams().setParameter(CoreProtocolPNames.USER_AGENT, com.netease.cloudmusic.utils.HttpRequest.USER_AGENT + "\r\n" + header.getName() + ":" + header.getValue()); } else { client.getParams().setParameter(CoreProtocolPNames.USER_AGENT, com.netease.cloudmusic.utils.HttpRequest.USER_AGENT); if (request instanceof RequestWrapper) { request = ((RequestWrapper) request).getOriginal(); } request.setHeader(header); } String host = isSecure ? ProxyUtils.SECURE_HOST : ProxyUtils.HOST; int port = isSecure ? ProxyUtils.SECURE_PORT : ProxyUtils.PORT; return new HttpRoute(target, null, new HttpHost(host, port), isSecure); } else { client.getParams().setParameter(CoreProtocolPNames.USER_AGENT, com.netease.cloudmusic.utils.HttpRequest.USER_AGENT); return new HttpRoute(target, null, isSecure); } } }); return client; } catch (Exception e) { e.printStackTrace(); return new DefaultHttpClient(); } } public static DefaultHttpClient createPlaintHttpClient() { try { KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); trustStore.load(null, null); PlainSSLSocketFactory socketFactory = new PlainSSLSocketFactory(trustStore); socketFactory.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); BasicHttpParams params = new BasicHttpParams(); HttpConnectionParams.setConnectionTimeout(params, 30000); HttpConnectionParams.setSoTimeout(params, 30000); HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1); HttpProtocolParams.setContentCharset(params, HTTP.UTF_8); SchemeRegistry registry = new SchemeRegistry(); registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); registry.register(new Scheme("https", socketFactory, 443)); ThreadSafeClientConnManager ccm = new ThreadSafeClientConnManager(params, registry); HttpClientParams.setCookiePolicy(params, CookiePolicy.BROWSER_COMPATIBILITY); final DefaultHttpClient client = new DefaultHttpClient(ccm, params); client.setRoutePlanner(new HttpRoutePlanner() { @Override public HttpRoute determineRoute(HttpHost target, HttpRequest arg1, HttpContext arg2) throws HttpException { client.getParams().setParameter(CoreProtocolPNames.USER_AGENT, com.netease.cloudmusic.utils.HttpRequest.USER_AGENT); return new HttpRoute(target, null, "https".equalsIgnoreCase(target.getSchemeName())); } }); return client; } catch (Exception e) { e.printStackTrace(); return new DefaultHttpClient(); } }