Java kullanarak kimlik doğrulaması gerektiren uzak URL'ye bağlanma


125

Java'da kimlik doğrulama gerektiren uzak bir URL'ye nasıl bağlanırım. Aşağıdaki kodu programlı olarak bir kullanıcı adı / parola sağlayabilmek için değiştirmenin bir yolunu bulmaya çalışıyorum, böylece bir 401 atmasın.

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

Yanıtlar:


134

Aşağıdaki gibi http istekleri için varsayılan kimlik doğrulayıcıyı ayarlayabilirsiniz:

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

Ayrıca, daha fazla esnekliğe ihtiyacınız varsa , size daha fazla kimlik doğrulama seçeneği (oturum desteği vb.) Sağlayacak olan Apache HttpClient'e göz atabilirsiniz .


4
Kötü bir kimlik doğrulama olayını nasıl idare edersiniz? [Örneğin, kullanıcı hiçbir şeyle eşleşmeyen kullanıcı adı ve parola kimlik doğrulama bilgileri sağlarsa]?
SK9

2
Yukarıdaki kod işe yarıyor ancak neler olup bittiğine dair oldukça örtülü. Orada alt sınıflandırma ve yöntemi geçersiz kılma var, neler olup bittiğini merak ediyorsanız bu sınıfların belgelerine bakın. Buradaki kod daha belirgindir javacodegeeks
Fuchida

12
Global olarak ayarlamak yerine Authenticatorbelirli URL.openConnection()çağrı başına özel ayarlamak mümkün müdür ?
Yuriy Nakonechnyy

@Yura: hayır. Küresel olmalı. Bununla birlikte, kimlik bilgilerini iş parçacığı yerel değişkenlerinden çeken genel bir kimlik doğrulayıcı ayarlamak ve HTTP bağlantısını yapmadan önce iş parçacığı başına kimlik bilgilerini ayarlamak gibi kötü şeyler yapabilirsiniz.
David

4
@YuriyNakonechnyy'ye yanıt olarak ... Java 9 veya üstü kullanıyorsanız, o zaman arayabilirsiniz HttpURLConnection.setAuthenticator(). Maalesef Java 8 ve önceki sürümlerde, Authenticator örneği JVM çapında genel bir değişkendir. Bakınız: docs.oracle.com/javase/9/docs/api/java/net/…
Neil Bartlett

134

Yalnızca aramanız için çalışan yerel ve daha az müdahaleci bir alternatif var.

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

5
Base64 sınıfı, Apache Commons Codec tarafından sağlanabilir.
Matthew Buckett

Benim için bu şekilde işe yaramadı ... Sadece James Van Huis'in iyi olmasının yolu
Miguel Ribeiro

Grails ve diğer birçok Java çerçevesinde 'yerel' çünkü hepsi Apache Commons Libs kullanıyor.
Wanderson Santos

1
.trim()Sonuç siz olmadıkça veya öbek çıktı üretmeyen bir yöntem değişkenini çağırmadıkça genel olarak çalışmaz. javax.xml.bind.DatatypeConverterdaha güvenli görünüyor.
Jesse Glick


77

Ayrıca, harici paketleri kullanmayı gerektirmeyen aşağıdakileri de kullanabilirsiniz:

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

10
Çok uzun zamandır java standart paketleri içinde bir Base64 kodlayıcı arıyordum! Teşekkür ederim
qwertzguy

Java9 + için --add-modules javax.xml.bind, paketi varsayılan sınıf yolundan kaldırdıkları için muhtemelen yapmanız gerekeceğini unutmayın . Ve Java11 + 'da tamamen kaldırıldı, tekrar harici bir bağımlılığa ihtiyacınız var. İlerleme böyle!
Ed Randall

1
@EdRandall bir java.util.Base64şimdi var, bu yüzden gerçekten ilerleme var :)
Steven Schlansker

42

Protokol ile etki alanı arasında kullanıcı adı ve parolayı girerken normal oturum açma kullanıyorsanız, bu daha basittir. Ayrıca oturum açarak ve oturum açmadan da çalışır.

Örnek URL: http: // kullanıcı: pass@domain.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();

Lütfen valerybodak'ın yorumunda Android geliştirme ortamında nasıl yapıldığına dikkat edin.


1
Bu tam olarak son 30 dakikadır aradığım şeydi. Çok teşekkürler!
Geert Schuring

Kullanıcı adınız / şifreniz özel karakterler içeriyorsa, bunları yeniden kodlamanız gerekeceğine inanıyorum. Ardından, yukarıdaki kod snippet'te sen geçerdi url.getUserInfo()thorugh URLDecoder.decode()ilk (@Peter Rader).
m01

Teşekkürler, ancak android için Base64'ü aşağıdaki gibi kullanmalısınız: String basicAuth = "Basic" + Base64.encodeToString (url.getUserInfo (). GetBytes (), Base64.DEFAULT); httpConn.setRequestProperty ("Yetkilendirme", basicAuth);
valerybodak

Bu tamamlama için teşekkür ederim valerybodak!
javabeangrinder

8

Buraya bir Android-Java-Cevap arayarak geldiğim için kısa bir özet yapacağım:

  1. Java.net.Authenticator'ı James van Huis tarafından gösterildiği gibi kullanın.
  2. Bu Cevapta olduğu gibi Apache Commons HTTP İstemcisini kullanın
  3. Temel java.net.URLConnection'ı kullanın ve burada gösterildiği gibi Authentication-Header'ı manuel olarak ayarlayın

Android'de Temel Kimlik Doğrulama ile java.net.URLConnection kullanmak istiyorsanız şu kodu deneyin:

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
Teşekkürler. Android'e özel bir cevap arıyordu!
Stephen McCormick

5

Kimlik doğrulamayı HttpsURLConnection kullanarak ayarlayabildim

           URL myUrl = new URL(httpsURL);
            HttpsURLConnection conn = (HttpsURLConnection)myUrl.openConnection();
            String userpass = username + ":" + password;
            String basicAuth = "Basic " + new String(Base64.getEncoder().encode(userpass.getBytes()));
            //httpsurlconnection
            conn.setRequestProperty("Authorization", basicAuth);

bu gönderiden birkaç değişiklik getirildi. ve Base64, java.util paketindendir.


3

"Base64 (). Encode ()" yaklaşımına gerçekten dikkat edin, ekibim ve ben 400 Apache hatalı istek sorunuyla karşılaştık çünkü bu, oluşturulan dizenin sonuna bir \ r \ n ekliyor.

Wireshark sayesinde paketleri koklarken bulduk.

İşte çözümümüz:

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

Umarım yardımcı olur!


3

Temel kimlik doğrulama için bu kodu kullanın.

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


2

Bağlantıyı açan kod üzerinde kontrolünüzün olmadığı duruma bir cevap vermek istiyorum. URLClassLoaderParola korumalı bir sunucudan bir jar dosyasını yüklemek için kullanırken yaptığım gibi .

AuthenticatorÇözüm işe ama ilk şifre olmadan ve sadece şifre birini sağlayan sunucu sorar sonra sunucuyu ulaşmaya çalıştığı dezavantajı olacaktır. Sunucunun bir şifreye ihtiyaç duyacağını zaten biliyorsanız, bu gereksiz bir gidiş dönüş.

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

}

Bu , kimlik bilgileri eklendiğinde mydeğiştirilen yeni bir protokolü kaydeder http. Yeni oluştururken Yani URLClassLoadersadece yerini httpile myve her şey yolunda. URLClassLoaderBir alan bir kurucu sağladığını biliyorum , URLStreamHandlerFactoryancak URL bir jar dosyasına işaret ediyorsa bu fabrika kullanılmıyor.


1

Java 9'dan beri bunu yapabilirsiniz

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

2
setAuthenticator()Yöntemi görmedim .
WesternGun

0

ANDROD UYGULAMASI Kullanıcı adı ve parola ile yetkilendirme isteyen web hizmetinden veri / dizi yanıtı istemek için eksiksiz bir yöntem

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

0

bunu bu şekilde yaptım bunu yapman gerekiyor sadece kopyala yapıştır mutlu ol

    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();
    }
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.