使用 HttpClient 在 Java 中进行 Http 基本身份验证?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3283234/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Http Basic Authentication in Java using HttpClient?
提问by Legend
I am trying to mimic the functionality of this curl command in Java:
我正在尝试在 Java 中模拟此 curl 命令的功能:
curl --basic --user username:password -d "" http://ipaddress/test/login
I wrote the following using Commons HttpClient 3.0 but somehow ended up getting an 500 Internal Server Error
from the server. Can someone tell me if I'm doing anything wrong?
我使用 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();
}
}
}
And I later tried a Commons HttpClient 4.0.1 but still the same error:
后来我尝试了一个 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();
}
}
采纳答案by Legend
Ok so this one works. Just in case anybody wants it, here's the version that works for me :)
好的,所以这个有效。以防万一有人想要它,这是对我有用的版本:)
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();
}
}
}
回答by Bruno
Here are a few points:
这里有几点:
You could consider upgrading to HttpClient 4 (generally speaking, if you can, I don't think version 3 is still actively supported).
A 500 status code is a server error, so it might be useful to see what the server says (any clue in the response body you're printing?). Although it might be caused by your client, the server shouldn't fail this way (a 4xx error code would be more appropriate if the request is incorrect).
I think
setDoAuthentication(true)
is the default (not sure). What could be useful to try is pre-emptive authentication works better:client.getParams().setAuthenticationPreemptive(true);
你可以考虑升级到 HttpClient 4(一般来说,如果可以的话,我认为版本 3 仍然没有得到积极支持)。
500 状态代码是服务器错误,因此查看服务器所说的内容可能很有用(您正在打印的响应正文中的任何线索?)。虽然它可能是由您的客户端引起的,但服务器不应该以这种方式失败(如果请求不正确,4xx 错误代码会更合适)。
我认为
setDoAuthentication(true)
是默认值(不确定)。尝试先发制人的身份验证效果更好:client.getParams().setAuthenticationPreemptive(true);
Otherwise, the main difference between curl -d ""
and what you're doing in Java is that, in addition to Content-Length: 0
, curl also sends Content-Type: application/x-www-form-urlencoded
. Note that in terms of design, you should probably send an entity with your POST
request anyway.
否则,curl -d ""
与您在 Java 中所做的事情之间的主要区别在于,除了 之外Content-Length: 0
,curl 还发送Content-Type: application/x-www-form-urlencoded
. 请注意,在设计方面,您可能POST
无论如何都应该随请求发送一个实体。
回答by Buhake Sindi
Have you tried this (using HttpClient version 4):
您是否尝试过此操作(使用 HttpClient 版本 4):
String encoding = Base64Encoder.encode(user + ":" + pwd);
HttpPost httpPost = new HttpPost("http://host:post/test/login");
httpPost.setHeader(HttpHeaders.AUTHORIZATION, "Basic " + encoding);
System.out.println("executing request " + httpPost.getRequestLine());
HttpResponse response = httpClient.execute(httpPost);
HttpEntity entity = response.getEntity();
回答by Ralph At skillyard
A small update - hopefully useful for somebody - it works for me in my project:
一个小更新 - 希望对某人有用 - 它在我的项目中对我有用:
I use the nice Public Domain class Base64.java from Robert Harder (Thanks Robert - Code availble here: Base64- download and put it in your package).
and make a download of a file (image, doc, etc.) with authentication and write to local disk
我使用了 Robert Harder 的不错的 Public Domain 类 Base64.java(感谢 Robert - 此处提供代码:Base64- 下载并将其放入您的包中)。
并通过身份验证下载文件(图像、文档等)并写入本地磁盘
Example:
例子:
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();
}
}
}
回答by lynhnn
HttpBasicAuth works for me with smaller changes
HttpBasicAuth 对我有用,更改较小
I use maven dependency
<dependency> <groupId>net.iharder</groupId> <artifactId>base64</artifactId> <version>2.3.8</version> </dependency>
Smaller change
String encoding = Base64.encodeBytes ((user + ":" + passwd).getBytes());
我使用 maven 依赖
<dependency> <groupId>net.iharder</groupId> <artifactId>base64</artifactId> <version>2.3.8</version> </dependency>
较小的变化
String encoding = Base64.encodeBytes ((user + ":" + passwd).getBytes());
回答by EngrSofty
for HttpClient always use HttpRequestInterceptor for example
对于 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);
回答by chenyi1976
Thanks for all answers above, but for me, I can not find Base64Encoder class, so I sort out my way anyway.
感谢上面的所有答案,但对我来说,我找不到 Base64Encoder 类,所以我无论如何都要整理一下。
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();
}
}
One more thing, I also tried
还有一件事,我也试过了
Base64.encodeBase64String("user:passwd".getBytes());
It does NOT work due to it return a string almost same with
它不起作用,因为它返回一个几乎相同的字符串
DatatypeConverter.printBase64Binary()
but end with "\r\n", then server will return "bad request".
但以“\r\n”结尾,则服务器将返回“错误请求”。
Also following code is working as well, actually I sort out this first, but for some reason, it does NOT work in some cloud environment (sae.sina.com.cn if you want to know, it is a chinese cloud service). so have to use the http header instead of HttpClient credentials.
下面的代码也能正常工作,其实我是先把这个整理出来的,但由于某种原因,它在某些云环境中不起作用(如果你想知道,它是一个中国云服务)。所以必须使用 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();
}
}
回答by Mario
This is the code from the accepted answer above, with some changes made regarding the Base64 encoding. The code below compiles.
这是上面接受的答案中的代码,对 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();
}
}
}
回答by manoj
while using Header array
使用 Header 数组时
String auth = Base64.getEncoder().encodeToString(("test1:test1").getBytes());
Header[] headers = {
new BasicHeader(HTTP.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString()),
new BasicHeader("Authorization", "Basic " +auth)
};
回答by rjdkolb
An easy wayto login with a HTTP POST without doing any Base64 specific callsis to use the HTTPClient BasicCredentialsProvider
使用 HTTP POST 登录而不进行任何 Base64 特定调用的简单方法是使用 HTTPClient BasicCredentialsProvider
import java.io.IOException;
import static java.lang.System.out;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.HttpClientBuilder;
//code
CredentialsProvider provider = new BasicCredentialsProvider();
UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(user, password);
provider.setCredentials(AuthScope.ANY, credentials);
HttpClient client = HttpClientBuilder.create().setDefaultCredentialsProvider(provider).build();
HttpResponse response = client.execute(new HttpPost("http://address/test/login"));//Replace HttpPost with HttpGet if you need to perform a GET to login
int statusCode = response.getStatusLine().getStatusCode();
out.println("Response Code :"+ statusCode);