J'essaie d'imiter les fonctionnalités de cette commande curl en Java:
curl --basic --user username:password -d "" http://ipaddress/test/login
J'ai écrit ce qui suit en utilisant Commons HttpClient 3.0, mais en fin de compte, j'ai obtenu un 500 Internal Server Error
du serveur. Quelqu'un peut-il me dire si je fais quelque chose de mal?
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();
}
}
}
Et j'ai essayé plus tard un Commons HttpClient 4.0.1 mais toujours la même erreur:
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();
}
}
Ok donc celui-ci fonctionne. Juste au cas où quelqu'un le voudrait, voici la version qui fonctionne pour moi :)
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();
}
}
}
Avez-vous essayé ceci (en utilisant HttpClient version 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();
C'est le code de la réponse acceptée ci-dessus, avec quelques modifications apportées au codage Base64. Le code ci-dessous est compilé.
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();
}
}
}
Une petite mise à jour - espérons utile pour quelqu'un - cela fonctionne pour moi dans mon projet:
J'utilise la classe Nice Public Domain Base64.Java de Robert Harder (Merci Robert - Code disponible ici: Base64 - téléchargez-le et mettez-le dans votre paquet).
et télécharger un fichier (image, doc, etc.) avec authentification et écrire sur le disque local
Exemple:
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();
}
}
}
Voici quelques points:
Vous pourriez envisager de passer à HttpClient 4 (en règle générale, si vous le pouvez, je ne pense pas que la version 3 soit toujours activement prise en charge).
Un code d'état 500 est une erreur de serveur. Il peut donc être utile de voir ce que dit le serveur (aucun indice dans le corps de la réponse que vous imprimez?). Bien que cela puisse être causé par votre client, le serveur ne devrait pas échouer de cette façon (un code d'erreur 4xx serait plus approprié si la requête est incorrecte).
Je pense que setDoAuthentication(true)
est la valeur par défaut (pas sûr). Ce qui pourrait être utile, c’est que l’authentification préventive fonctionne mieux:
client.getParams().setAuthenticationPreemptive(true);
Sinon, la principale différence entre curl -d ""
et ce que vous faites dans Java est que, en plus de Content-Length: 0
, curl envoie également Content-Type: application/x-www-form-urlencoded
. Notez qu'en termes de conception, vous devriez quand même probablement envoyer une entité avec votre demande POST
.
Merci pour toutes les réponses ci-dessus, mais pour moi, je ne trouve pas la classe Base64Encoder, je règle donc mon chemin de toute façon.
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();
}
}
Une dernière chose, j'ai aussi essayé
Base64.encodeBase64String("user:passwd".getBytes());
Cela ne fonctionne PAS car il retourne une chaîne presque identique à
DatatypeConverter.printBase64Binary()
mais se terminant par "\ r\n", le serveur renverra "demande incorrecte".
Le code suivant fonctionne également. En fait, je règle ce problème en premier, mais pour une raison quelconque, il ne fonctionne PAS dans un environnement cloud (sae.sina.com.cn, si vous voulez savoir, il s’agit d’un service cloud chinois). il faut donc utiliser l'en-tête http au lieu des identifiants 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 fonctionne pour moi avec de plus petits changements
J'utilise la dépendance maven
<dependency>
<groupId>net.iharder</groupId>
<artifactId>base64</artifactId>
<version>2.3.8</version>
</dependency>
Petit changement
String encoding = Base64.encodeBytes ((user + ":" + passwd).getBytes());
en utilisant le tableau d'en-tête
String auth = Base64.getEncoder().encodeToString(("test1:test1").getBytes());
Header[] headers = {
new BasicHeader(HTTP.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString()),
new BasicHeader("Authorization", "Basic " +auth)
};
pour HttpClient utilisez toujours HttpRequestInterceptor par exemple
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);
Un moyen facile de vous connecter avec un HTTP POST sans faire des appels spécifiques à Base64 consiste à utiliser 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);