2009-01-30 29 views
98

Jak połączyć się ze zdalnym adresem URL w języku Java, który wymaga uwierzytelnienia. Staram się znaleźć sposób, aby zmodyfikować poniższy kod, aby móc programowo podać nazwę użytkownika/hasło, więc nie rzucać 401.Podłączanie do zdalnego adresu URL wymagającego uwierzytelniania za pomocą Java

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

Odpowiedz

112

Można ustawić domyślny Authenticator dla żądań HTTP, takich jak ten :

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

Ponadto, jeśli wymagać większej elastyczności, można zapoznać się z Apache HttpClient, co daje więcej opcji uwierzytelniania (jak również wsparcie sesji, etc.)

+3

Jak radzisz sobie ze złym uwierzytelnieniem? [Na przykład, jeśli użytkownik podaje poświadczenia uwierzytelniające nazwę użytkownika i hasło, które nie pasują do niczego]? – SK9

+3

Ta odpowiedź uratowała mi dzień! –

+2

Powyższy kod działa, ale jest całkowicie niejawny co do tego, co się dzieje. Tam jest nadpisywanie i nadpisywanie metod tam, kopiuj do dokumentów dla tych klas, jeśli chcesz wiedzieć, co się dzieje. Kod jest bardziej wyraźny [javacodegeeks] (http://examples.javacodegeeks.com/core-java/net/authenticator/access-password-protected-url-with-authenticator/) – Fuchida

91

Jest rodowitym i mniej inwazyjne alternatywa, która działa tylko dla y nasz telefon.

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

Klasa Base64 może być dostarczana przez kodek Apache Commons. –

+0

Nie działa dla mnie w ten sposób ... Jedynie sposób, w jaki @James Van Huis był dobry –

+1

pracował dla mnie! Dzięki! – Paul

62

Można również użyć następujących, który nie wymaga korzystania pakiety zewnętrzne:

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

Od tak dawna szukałem kodera Base64 w standardowych pakietach java! Dziękuję – qwertzguy

+6

Dzięki za wskaźnik do "natywnego" kodera Base64! –

31

Jeśli używasz normalnej logowanie przy jednoczesnym wprowadzeniu nazwy użytkownika i hasła pomiędzy protokołem a domeną jest to prostsze. Działa również z i bez logowania.

Próbka Url: http://user:[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(); 
+0

To zadziałało dla mnie świetnie. Dzięki! –

+1

To było * dokładnie * to, czego szukałem przez ostatnie 30 minut. Wielkie dzięki! –

+0

Nie działa, jeśli podanie zawiera # –

3

być bardzo ostrożny z podejściem "Base64() zakodować()", mój zespół i mam 400 Apache problemy Bad Request ponieważ dodaje \ r \ n na koniec generowanego łańcucha.

Znaleźliśmy to wąchanie pakietów dzięki Wireshark.

Oto nasze rozwiązanie:

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

Nadzieję, że to pomaga!

8

jakom przyszedł tutaj szuka Android Java odebrania mam zamiar zrobić krótkie podsumowanie:

  1. Używaj java.net.Authenticator jak pokazano James van Huis
  2. użytkowania Apache fotografia HTTP Client, jak w this Answer
  3. używać podstawowych java.net.URLConnection i ustawić ręcznie Authentication-header jak pokazano here

Jeśli chcesz użyć java.net.URLConnection z uwierzytelniania podstawowego w Androida wypróbować ten kod:

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 
+1

Dzięki. Szukał konkretnej odpowiedzi na Androida! –

0

Androd REALIZACJA Kompletny sposób do żądania danych/odpowiedź ciąg z usługi internetowej wystąpieniem o pozwolenie się podając nazwę użytkownika i hasło

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

Użyj tego kodu do podstawowego uwierzytelnienia.

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

1

Chciałbym udzielić odpowiedzi dla przypadku, że nie masz kontroli nad kodem, który otwiera połączenie. Link zrobiłem, gdy użyłem URLClassLoader do załadowania pliku JAR z serwera chronionego hasłem.

Rozwiązanie Authenticator działałoby, ale ma tę wadę, że najpierw próbuje dotrzeć do serwera bez hasła i dopiero po tym, gdy serwer poprosi o podanie hasła. To niepotrzebny objazd, jeśli już wiesz, że serwer potrzebuje hasł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; 
    } 

} 

Rejestruje nowy protokół my, który jest zastąpiony przez http gdy poświadczenia są dodawane. Dlatego przy tworzeniu nowego URLClassLoader wystarczy zamienić http na my i wszystko jest w porządku. Wiem, że URLClassLoader dostarcza konstruktora, który pobiera URLStreamHandlerFactory, ale ta fabryka nie jest używana, jeśli adres URL wskazuje na plik JAR.

Powiązane problemy