Connessione all’URL remoto che richiede l’autenticazione tramite Java

Come posso connettermi a un URL remoto in Java che richiede l’autenticazione. Sto cercando di trovare un modo per modificare il seguente codice per poter fornire in modo programmatico un nome utente / una password in modo da non lanciare un 401.

URL url = new URL(String.format("http://%s/manager/list", _host + ":8080")); HttpURLConnection connection = (HttpURLConnection)url.openConnection(); 

Puoi impostare l’autenticatore predefinito per le richieste http in questo modo:

 Authenticator.setDefault (new Authenticator() { protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication ("username", "password".toCharArray()); } }); 

Inoltre, se hai bisogno di maggiore flessibilità, puoi controllare Apache HttpClient , che ti darà più opzioni di autenticazione (oltre al supporto di sessione, ecc.)

C’è un’alternativa nativa e meno invadente, che funziona solo per la tua chiamata.

 URL url = new URL(“location address”); URLConnection uc = url.openConnection(); String userpass = username + ":" + password; String basicAuth = "Basic " + new String(Base64.getEncoder().encode(userpass.getBytes())); uc.setRequestProperty ("Authorization", basicAuth); InputStream in = uc.getInputStream(); 

Puoi anche usare quanto segue, che non richiede l’uso di pacchetti esterni:

 URL url = new URL(“location address”); URLConnection uc = url.openConnection(); String userpass = username + ":" + password; String basicAuth = "Basic " + javax.xml.bind.DatatypeConverter.printBase64Binary(userpass.getBytes()); uc.setRequestProperty ("Authorization", basicAuth); InputStream in = uc.getInputStream(); 

Se stai utilizzando il normale login mentre inserisci il nome utente e la password tra il protocollo e il dominio, questo è più semplice. Funziona anche con e senza login.

URL di esempio: http: // utente: [email protected]/url

 URL url = new URL("http://user:[email protected]/url"); URLConnection urlConnection = url.openConnection(); if (url.getUserInfo() != null) { String basicAuth = "Basic " + new String(new Base64().encode(url.getUserInfo().getBytes())); urlConnection.setRequestProperty("Authorization", basicAuth); } InputStream inputStream = urlConnection.getInputStream(); 

Come sono venuto qui alla ricerca di una risposta Java-Android, ho intenzione di fare un breve riassunto:

  1. Usa java.net.Authenticator come mostrato da James van Huis
  2. Utilizzare il client HTTP Apache Commons , come in questa risposta
  3. Usa basic java.net.URLConnection e imposta l’Authentication-Header manualmente come mostrato qui

Se si desidera utilizzare java.net.URLConnection con l’autenticazione di base in Android, provare questo codice:

 URL url = new URL("http://www.mywebsite.com/resource"); URLConnection urlConnection = url.openConnection(); String header = "Basic " + new String(android.util.Base64.encode("user:pass".getBytes(), android.util.Base64.NO_WRAP)); urlConnection.addRequestProperty("Authorization", header); // go on setting more request headers, reading the response, etc 

State molto attenti con l’approccio “Base64 (). Encode ()”, il mio team e io abbiamo avuto 400 problemi di richiesta errata di Apache perché aggiunge un \ r \ n alla fine della stringa generata.

Lo abbiamo trovato annusando i pacchetti grazie a Wireshark.

Ecco la nostra soluzione:

 import org.apache.commons.codec.binary.Base64; HttpGet getRequest = new HttpGet(endpoint); getRequest.addHeader("Authorization", "Basic " + getBasicAuthenticationEncoding()); private String getBasicAuthenticationEncoding() { String userPassword = username + ":" + password; return new String(Base64.encodeBase64(userPassword.getBytes())); } 

Spero che sia d’aiuto!

Utilizzare questo codice per l’autenticazione di base.

 URL url = new URL(path); String userPass = "username:password"; String basicAuth = "Basic " + Base64.encodeToString(userPass.getBytes(), Base64.DEFAULT);//or //String basicAuth = "Basic " + new String(Base64.encode(userPass.getBytes(), Base64.No_WRAP)); HttpURLConnection urlConnection = (HttpURLConnection)url.openConnection(); urlConnection.setRequestProperty("Authorization", basicAuth); urlConnection.connect(); 

Vorrei fornire una risposta per il caso in cui non si ha il controllo sul codice che apre la connessione. Come ho fatto quando uso URLClassLoader per caricare un file jar da un server protetto da password.

La soluzione Authenticator funzionerebbe ma ha lo svantaggio di provare prima a raggiungere il server senza password e solo dopo che il server chiede una password ne fornisce una. Questo è un roundtrip non necessario se sai già che il server avrebbe bisogno di una password.

 public class MyStreamHandlerFactory implements URLStreamHandlerFactory { private final ServerInfo serverInfo; public MyStreamHandlerFactory(ServerInfo serverInfo) { this.serverInfo = serverInfo; } @Override public URLStreamHandler createURLStreamHandler(String protocol) { switch (protocol) { case "my": return new MyStreamHandler(serverInfo); default: return null; } } } public class MyStreamHandler extends URLStreamHandler { private final String encodedCredentials; public MyStreamHandler(ServerInfo serverInfo) { String strCredentials = serverInfo.getUsername() + ":" + serverInfo.getPassword(); this.encodedCredentials = Base64.getEncoder().encodeToString(strCredentials.getBytes()); } @Override protected URLConnection openConnection(URL url) throws IOException { String authority = url.getAuthority(); String protocol = "http"; URL directUrl = new URL(protocol, url.getHost(), url.getPort(), url.getFile()); HttpURLConnection connection = (HttpURLConnection) directUrl.openConnection(); connection.setRequestProperty("Authorization", "Basic " + encodedCredentials); return connection; } } 

Questo registra un nuovo protocollo my che viene sostituito da http quando vengono aggiunte le credenziali. Quindi quando si crea il nuovo URLClassLoader basta sostituire http con my e tutto va bene. So che URLClassLoader fornisce un costruttore che accetta un URLStreamHandlerFactory ma questo factory non viene utilizzato se l’URL punta a un file jar.

ANDROD IMPLEMENTAZIONE Un metodo completo per richiedere dati / risposta stringa dal servizio web che richiede l’authorization con nome utente e password

 public static String getData(String uri, String userName, String userPassword) { BufferedReader reader = null; byte[] loginBytes = (userName + ":" + userPassword).getBytes(); StringBuilder loginBuilder = new StringBuilder() .append("Basic ") .append(Base64.encodeToString(loginBytes, Base64.DEFAULT)); try { URL url = new URL(uri); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.addRequestProperty("Authorization", loginBuilder.toString()); StringBuilder sb = new StringBuilder(); reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); String line; while ((line = reader.readLine())!= null){ sb.append(line); sb.append("\n"); } return sb.toString(); } catch (Exception e) { e.printStackTrace(); return null; } finally { if (null != reader){ try { reader.close(); } catch (IOException e) { e.printStackTrace(); } } } } 

l’ho fatto in questo modo è necessario fare questo basta copiare incollarlo per essere felice

  HttpURLConnection urlConnection; String url; // String data = json; String result = null; try { String username ="[email protected]"; String password = "12345678"; String auth =new String(username + ":" + password); byte[] data1 = auth.getBytes(UTF_8); String base64 = Base64.encodeToString(data1, Base64.NO_WRAP); //Connect urlConnection = (HttpURLConnection) ((new URL(urlBasePath).openConnection())); urlConnection.setDoOutput(true); urlConnection.setRequestProperty("Content-Type", "application/json"); urlConnection.setRequestProperty("Authorization", "Basic "+base64); urlConnection.setRequestProperty("Accept", "application/json"); urlConnection.setRequestMethod("POST"); urlConnection.setConnectTimeout(10000); urlConnection.connect(); JSONObject obj = new JSONObject(); obj.put("MobileNumber", "+97333746934"); obj.put("EmailAddress", "[email protected]"); obj.put("FirstName", "Danish"); obj.put("LastName", "Hussain"); obj.put("Country", "BH"); obj.put("Language", "EN"); String data = obj.toString(); //Write OutputStream outputStream = urlConnection.getOutputStream(); BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream, "UTF-8")); writer.write(data); writer.close(); outputStream.close(); int responseCode=urlConnection.getResponseCode(); if (responseCode == HttpsURLConnection.HTTP_OK) { //Read BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream(), "UTF-8")); String line = null; StringBuilder sb = new StringBuilder(); while ((line = bufferedReader.readLine()) != null) { sb.append(line); } bufferedReader.close(); result = sb.toString(); }else { // return new String("false : "+responseCode); new String("false : "+responseCode); } } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (JSONException e) { e.printStackTrace(); } 

Da Java 9, puoi farlo

 URL url = new URL("http://www.example.com"); HttpURLConnection connection = (HttpURLConnection)url.openConnection(); connection.setAuthenticator(new Authenticator() { protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication ("USER", "PASS".toCharArray()); } });