Autenticazione di base Http in Java utilizzando HttpClient?

Sto cercando di imitare la funzionalità di questo comando di arricciatura in Java:

curl --basic --user username:password -d "" http://ipaddress/test/login 

Ho scritto quanto segue usando Commons HttpClient 3.0 ma in qualche modo ho finito per ottenere un 500 Internal Server Error del server 500 Internal Server Error dal server. Qualcuno può dirmi se sto facendo qualcosa di sbagliato?

 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(); } } } 

E in seguito ho provato un Commons HttpClient 4.0.1 ma ancora lo stesso errore:

 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(); } } 

Hai provato questo (utilizzando HttpClient versione 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(); 

Ok, questo funziona. Nel caso in cui qualcuno lo volesse, ecco la versione che funziona per 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(); } } } 

Questo è il codice della risposta accettata sopra, con alcune modifiche apportate alla codifica Base64. Il codice qui sotto è compilato.

 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(); } } } 

Un piccolo aggiornamento – si spera utile per qualcuno – funziona per me nel mio progetto:

  • Io uso la bella class Public Domain Base64.java di Robert Harder (Grazie Robert – Codice availble qui: Base64 – scarica e inseriscilo nel pacchetto).

  • e fare un download di un file (immagine, doc, ecc.) con autenticazione e scrivere su disco locale

Esempio:

 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(); } } } 

Ecco alcuni punti:

  • Potresti considerare l’aggiornamento a HttpClient 4 (in generale, se puoi, non credo che la versione 3 sia ancora supportata triggersmente).

  • Un codice di stato 500 è un errore del server, quindi potrebbe essere utile vedere cosa dice il server (qualsiasi indizio nel corpo della risposta che si sta stampando?). Anche se potrebbe essere causato dal tuo client, il server non dovrebbe fallire in questo modo (un codice di errore 4xx sarebbe più appropriato se la richiesta non è corretta).

  • Penso che setDoAuthentication(true) sia l’impostazione predefinita (non è sicuro). Ciò che potrebbe essere utile provare è che l’autenticazione preventiva funziona meglio:

     client.getParams().setAuthenticationPreemptive(true); 

Altrimenti, la differenza principale tra curl -d "" e quello che stai facendo in Java è che, oltre a Content-Length: 0 , curl invia anche Content-Type: application/x-www-form-urlencoded . Nota che in termini di design, dovresti probabilmente inviare un’entity framework con la tua richiesta POST comunque.

Grazie per tutte le risposte di cui sopra, ma per me, non riesco a trovare la class Base64Encoder, quindi ho comunque risolto la mia strada.

 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(); } } 

Un’altra cosa, ho anche provato

 Base64.encodeBase64String("user:passwd".getBytes()); 

NON funziona perché restituisce una stringa quasi uguale a

 DatatypeConverter.printBase64Binary() 

ma termina con “\ r \ n”, quindi il server restituirà “ctriggers richiesta”.

Anche il codice seguente sta funzionando, in realtà lo risolvo prima, ma per qualche ragione, NON funziona in alcuni ambienti cloud (sae.sina.com.cn se vuoi sapere, è un servizio cloud cinese). quindi è necessario utilizzare l’intestazione http anziché le credenziali 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(); } } 

per HttpClient usa sempre HttpRequestInterceptor per esempio

 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); 

HttpBasicAuth funziona per me con piccole modifiche

  1. Uso la dipendenza di Maven

      net.iharder base64 2.3.8  
  2. Piccolo cambiamento

     String encoding = Base64.encodeBytes ((user + ":" + passwd).getBytes()); 

mentre si utilizza la matrice di intestazione

 String auth = Base64.getEncoder().encodeToString(("test1:test1").getBytes()); Header[] headers = { new BasicHeader(HTTP.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString()), new BasicHeader("Authorization", "Basic " +auth) }; 

Un modo semplice per accedere con un POST HTTP senza effettuare alcuna chiamata specifica Base64 è utilizzare 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);