可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I am trying to mimic the functionality of this curl command in Java:
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?
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:
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();
}
}
回答1:
Have you tried this (using HttpClient version 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();
回答2:
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();
}
}
}
回答3:
This is the code from the accepted answer above, with some changes made regarding the Base64 encoding. The code below compiles.
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();
}
}
}
回答4:
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
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();
}
}
}
回答5:
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);
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.
回答6:
Thanks for all answers above, but for me, I can not find Base64Encoder class, so I sort out my way anyway.
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\".
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.
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();
}
}
回答7:
for HttpClient always use HttpRequestInterceptor
for example
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);
回答8:
HttpBasicAuth works for me with smaller changes
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());
回答9:
while using Header array
String auth = Base64.getEncoder().encodeToString((\"test1:test1\").getBytes());
Header[] headers = {
new BasicHeader(HTTP.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString()),
new BasicHeader(\"Authorization\", \"Basic \" +auth)
};
回答10:
An easy way to login with a HTTP POST without doing any Base64 specific calls is to use the 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);