Java中使用HttpClient的HTTP基本身份validation?
我试图在Java中模仿这个curl命令的function:
curl --basic --user username:password -d "" http://ipaddress/test/login
我使用Commons HttpClient 3.0编写了以下内容,但不知何故最终从服务器获得了500 Internal Server Error
。 有人可以告诉我,如果我做错了什么?
public class HttpBasicAuth { private static final String ENCODING = "UTF-8"; /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub try { HttpClient client = new HttpClient(); client.getState().setCredentials( new AuthScope("ipaddress", 443, "realm"), new UsernamePasswordCredentials("test1", "test1") ); PostMethod post = new PostMethod( "http://address/test/login"); post.setDoAuthentication( true ); try { int status = client.executeMethod( post ); System.out.println(status + "\n" + post.getResponseBodyAsString()); } finally { // release any connection resources used by the method post.releaseConnection(); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
我后来尝试了一个Commons HttpClient 4.0.1,但仍然是一样的错误:
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.auth.AuthScope; import org.apache.http.auth.UsernamePasswordCredentials; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.methods.HttpPost; import org.apache.http.impl.client.DefaultHttpClient; public class HttpBasicAuth { private static final String ENCODING = "UTF-8"; /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub try { DefaultHttpClient httpclient = new DefaultHttpClient(); httpclient.getCredentialsProvider().setCredentials( new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT), new UsernamePasswordCredentials("test1", "test1")); HttpPost httppost = new HttpPost("http://host:post/test/login"); System.out.println("executing request " + httppost.getRequestLine()); HttpResponse response; response = httpclient.execute(httppost); HttpEntity entity = response.getEntity(); System.out.println("----------------------------------------"); System.out.println(response.getStatusLine()); if (entity != null) { System.out.println("Response content length: " + entity.getContentLength()); } if (entity != null) { entity.consumeContent(); } httpclient.getConnectionManager().shutdown(); } catch (ClientProtocolException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
你有没有尝试过(使用HttpClient版本4)
String encoding = Base64Encoder.encode ("test1:test1"); HttpPost httppost = new HttpPost("http://host:post/test/login"); httppost.setHeader("Authorization", "Basic " + encoding); System.out.println("executing request " + httppost.getRequestLine()); HttpResponse response = httpclient.execute(httppost); HttpEntity entity = response.getEntity();
好,所以这个工程。 以防万一谁想要它,这里的版本适合我:)
import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; import java.util.Base64; public class HttpBasicAuth { public static void main(String[] args) { try { URL url = new URL ("http://ip:port/login"); String encoding = Base64.getEncoder().encodeToString(("test1:test1").getBytes("UTF-8")); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("POST"); connection.setDoOutput(true); connection.setRequestProperty ("Authorization", "Basic " + encoding); InputStream content = (InputStream)connection.getInputStream(); BufferedReader in = new BufferedReader (new InputStreamReader (content)); String line; while ((line = in.readLine()) != null) { System.out.println(line); } } catch(Exception e) { e.printStackTrace(); } } }
一个小小的更新 – 希望对别人有用 – 它适用于我在我的项目中:
-
我使用来自Robert Harder的好的公共领域类Base64.java(感谢罗伯特 – 代码在这里: Base64 – 下载并把它放在你的包中)。
-
并通过authentication下载文件(图像,文档等)并写入本地磁盘
例:
import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; public class HttpBasicAuth { public static void downloadFileWithAuth(String urlStr, String user, String pass, String outFilePath) { try { // URL url = new URL ("http://ip:port/download_url"); URL url = new URL(urlStr); String authStr = user + ":" + pass; String authEncoded = Base64.encodeBytes(authStr.getBytes()); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("GET"); connection.setDoOutput(true); connection.setRequestProperty("Authorization", "Basic " + authEncoded); File file = new File(outFilePath); InputStream in = (InputStream) connection.getInputStream(); OutputStream out = new BufferedOutputStream(new FileOutputStream(file)); for (int b; (b = in.read()) != -1;) { out.write(b); } out.close(); in.close(); } catch (Exception e) { e.printStackTrace(); } } }
这是上面接受的答案中的代码,对Base64编码进行了一些更改。 下面的代码编译。
import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; import org.apache.commons.codec.binary.Base64; public class HttpBasicAuth { public static void main(String[] args) { try { URL url = new URL ("http://ip:port/login"); Base64 b = new Base64(); String encoding = b.encodeAsString(new String("test1:test1").getBytes()); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("POST"); connection.setDoOutput(true); connection.setRequestProperty ("Authorization", "Basic " + encoding); InputStream content = (InputStream)connection.getInputStream(); BufferedReader in = new BufferedReader (new InputStreamReader (content)); String line; while ((line = in.readLine()) != null) { System.out.println(line); } } catch(Exception e) { e.printStackTrace(); } } }
这里有几点:
-
你可以考虑升级到HttpClient 4(一般来说,如果可以,我不认为版本3仍然是积极支持)。
-
500状态码是一个服务器错误,所以看看服务器说什么(你正在打印的响应正文中的任何线索)可能是有用的。 虽然这可能是由客户端引起的,但服务器不应该以这种方式失败(如果请求不正确,4xx错误代码会更合适)。
-
我认为
setDoAuthentication(true)
是默认的(不确定)。 有什么可以尝试的是先发制人的authentication更好地工作:client.getParams().setAuthenticationPreemptive(true);
否则, curl -d ""
和你在Java中所做的主要区别在于除了Content-Length: 0
,curl还会发送Content-Type: application/x-www-form-urlencoded
。 请注意,就devise而言,无论如何您都应该发送一个实体与您的POST
请求。
对于HttpClient总是使用HttpRequestInterceptor为例
httclient.addRequestInterceptor(new HttpRequestInterceptor() { public void process(HttpRequest arg0, HttpContext context) throws HttpException, IOException { AuthState state = (AuthState) context.getAttribute(ClientContext.TARGET_AUTH_STATE); if (state.getAuthScheme() == null) { BasicScheme scheme = new BasicScheme(); CredentialsProvider credentialsProvider = (CredentialsProvider) context.getAttribute(ClientContext.CREDS_PROVIDER); Credentials credentials = credentialsProvider.getCredentials(AuthScope.ANY); if (credentials == null) { System.out.println("Credential >>" + credentials); throw new HttpException(); } state.setAuthScope(AuthScope.ANY); state.setAuthScheme(scheme); state.setCredentials(credentials); } } }, 0);
感谢上面的所有答案,但对于我来说,我无法findBase64Encoder类,所以我总理我的方式。
public static void main(String[] args) { try { DefaultHttpClient Client = new DefaultHttpClient(); HttpGet httpGet = new HttpGet("https://httpbin.org/basic-auth/user/passwd"); String encoding = DatatypeConverter.printBase64Binary("user:passwd".getBytes("UTF-8")); httpGet.setHeader("Authorization", "Basic " + encoding); HttpResponse response = Client.execute(httpGet); System.out.println("response = " + response); BufferedReader breader = new BufferedReader(new InputStreamReader(response.getEntity().getContent())); StringBuilder responseString = new StringBuilder(); String line = ""; while ((line = breader.readLine()) != null) { responseString.append(line); } breader.close(); String repsonseStr = responseString.toString(); System.out.println("repsonseStr = " + repsonseStr); } catch (IOException e) { e.printStackTrace(); } }
还有一件事,我也试过了
Base64.encodeBase64String("user:passwd".getBytes());
它不工作,因为它返回一个string几乎相同
DatatypeConverter.printBase64Binary()
但以“\ r \ n”结尾,则服务器将返回“不良请求”。
下面的代码也在运行,实际上我首先要理清这个,但是由于某种原因,它在某些云环境(sae.sina.com.cn,如果你想知道,这是一个中国云服务)不起作用。 所以必须使用http标头而不是HttpClient凭证。
public static void main(String[] args) { try { DefaultHttpClient Client = new DefaultHttpClient(); Client.getCredentialsProvider().setCredentials( AuthScope.ANY, new UsernamePasswordCredentials("user", "passwd") ); HttpGet httpGet = new HttpGet("https://httpbin.org/basic-auth/user/passwd"); HttpResponse response = Client.execute(httpGet); System.out.println("response = " + response); BufferedReader breader = new BufferedReader(new InputStreamReader(response.getEntity().getContent())); StringBuilder responseString = new StringBuilder(); String line = ""; while ((line = breader.readLine()) != null) { responseString.append(line); } breader.close(); String responseStr = responseString.toString(); System.out.println("responseStr = " + responseStr); } catch (IOException e) { e.printStackTrace(); } }
HttpBasicAuth适用于我的更改较小
-
我使用maven依赖
<dependency> <groupId>net.iharder</groupId> <artifactId>base64</artifactId> <version>2.3.8</version> </dependency>
-
较小的变化
String encoding = Base64.encodeBytes ((user + ":" + passwd).getBytes());