Conexión a una URL remota que requiere autenticación usando Java

¿Cómo me conecto a una URL remota en Java que requiere autenticación? Estoy tratando de encontrar una forma de modificar el siguiente código para poder proporcionar programáticamente un nombre de usuario / contraseña para que no arroje un 401.

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

Puede configurar el autenticador predeterminado para solicitudes http como esta:

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

Además, si necesita más flexibilidad, puede consultar Apache HttpClient , que le brindará más opciones de autenticación (así como soporte de sesión, etc.)

Hay una alternativa nativa y menos intrusiva, que funciona solo para su llamada.

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

También puede usar lo siguiente, que no requiere el uso de paquetes externos:

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

Si está utilizando el inicio de sesión normal al ingresar el nombre de usuario y la contraseña entre el protocolo y el dominio, esto es más simple. También funciona con y sin inicio de sesión.

URL de ejemplo: http: // usuario: pase@dominio.com/url

 URL url = new URL("http://user:pass@domain.com/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(); 

Como vine aquí en busca de una respuesta Android-Java, voy a hacer un breve resumen:

  1. Use java.net.Authenticator como lo muestra James van Huis
  2. Utilice Apache Commons HTTP Client , como en esta respuesta
  3. Use java.net.URLConnection básico y establezca Authentication-Header manualmente como se muestra aquí

Si desea usar java.net.URLConnection con Autenticación básica en Android intente este código:

 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 

Tenga mucho cuidado con el enfoque “Base64 (). Encode ()”, mi equipo y yo obtuvimos 400 problemas de solicitud incorrecta de Apache porque agrega un \ r \ n al final de la cadena generada.

Lo encontramos oliendo paquetes gracias a Wireshark.

Aquí está nuestra solución:

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

¡Espero eso ayude!

Use este código para autenticación básica.

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

Me gustaría proporcionar una respuesta para el caso de que no tienes control sobre el código que abre la conexión. Como lo hice cuando URLClassLoader para cargar un archivo jar desde un servidor protegido por contraseña.

La solución Authenticator funcionaría pero tiene el inconveniente de que primero trata de llegar al servidor sin una contraseña y solo después de que el servidor solicite una contraseña la proporciona. Es una ida y vuelta innecesaria si ya sabes que el servidor necesitaría una contraseña.

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

Esto registra un nuevo protocolo my que es reemplazado por http cuando se agregan las credenciales. Entonces, al crear el nuevo URLClassLoader simplemente reemplace http con my y todo está bien. Sé que URLClassLoader proporciona un constructor que toma una URLStreamHandlerFactory pero esta fábrica no se usa si la URL apunta a un archivo jar.

IMPLEMENTACIÓN ANDROD Un método completo para solicitar datos / cadena de respuesta del servicio web que solicita autorización con nombre de usuario y contraseña

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

Lo hice de esta manera que necesitas hacer esto solo copiar pegarlo ser feliz

  HttpURLConnection urlConnection; String url; // String data = json; String result = null; try { String username ="danish.hussain@gmail.com"; 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", "danish.hussain@mee.com"); 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(); } 

Desde Java 9, puedes hacer esto

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