Підключення до віддаленої URL-адреси, яка вимагає автентифікації за допомогою Java


125

Як підключитися до віддаленої URL-адреси Java, яка вимагає автентифікації. Я намагаюся знайти спосіб змінити наступний код, щоб мати можливість програмно надати ім’я користувача / пароль, щоб він не кидав 401.

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

Відповіді:


134

Ви можете встановити автентифікатор за замовчуванням для таких запитів http:

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

Також якщо вам потрібна більша гнучкість, ви можете перевірити Apache HttpClient , який надасть вам більше варіантів аутентифікації (а також підтримку сеансу тощо)


4
Як ви поводите погану подію аутентифікації? [Наприклад, якщо користувач надає облікові дані автентифікації імені користувача та пароля, які нічого не відповідають]?
SK9

2
Наведений вище код працює, але досить неявно щодо того, що відбувається. Там відбувається підкласифікація і переосмислення методів, викопайте документи в цих класах, якщо ви хочете знати, що відбувається. Код тут більш явний javacodegeeks
Фухіда,

12
Чи можна встановити Authenticatorконкретну URL.openConnection()виклик, а не встановити її глобально?
Юрій Наконечний

@Юра: ні. Це має бути глобальним. Однак ви можете робити злі речі, такі як встановлення глобального аутентифікатора, який витягує облікові дані з локальних змінних потоків, і встановлює облікові дані на потік, перш ніж здійснювати з'єднання HTTP.
Девід Даний

4
У відповідь на @YuriyNakonechnyy ... якщо ви використовуєте Java 9 або вище, то ви можете зателефонувати HttpURLConnection.setAuthenticator(). На жаль, на Java 8 і новіших версіях, екземпляр Authenticator - глобальна змінна JVM. Дивіться: docs.oracle.com/javase/9/docs/api/java/net/…
Ніл Бартлетт

133

Є рідна і менш нав'язлива альтернатива, яка працює лише для вашого дзвінка.

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 може надавати Apache Commons Codec.
Меттью Бакетт

Мені так не вийшло ... Тільки так, як @James Van Huis був гарний
Мігель Рібейро

Це "рідне" для Grails та багатьох інших фреймворків Java, оскільки всі вони використовують Apache Commons Libs.
Вандерсон Сантос

1
Загалом не працює, якщо ви не отримаєте .trim()результат, або не зателефонуйте у варіант методу, який не дає збитку. javax.xml.bind.DatatypeConverterздається безпечнішим.
Джессі Глік

Я процитував ваш код у цій відповіді Спасибі
notes-jj

77

Ви також можете використовувати наступне, що не вимагає використання зовнішніх пакетів:

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
Я так довго шукав кодер Base64 всередині стандартних пакетів Java! Дякую
qwertzguy

Зауважте, що для Java9 + вам, мабуть, доведеться, --add-modules javax.xml.bindоскільки вони видалили пакунок із стандартного класу. А в Java11 + це видалено взагалі, вам знову потрібна зовнішня залежність. Такий прогрес!
Ед Рендалл

1
@EdRandall є java.util.Base64зараз, так що це справді прогрес :)
Стівен Шланскер

42

Якщо ви використовуєте звичайний логін, вводячи ім'я користувача та пароль між протоколом і доменом, це простіше. Він також працює з і без входу.

Приклад URL- адреси : http: // user: 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();

Зверніть увагу на коментар із валерібодаку нижче, як це робиться в середовищі розробки Android.


1
Це саме те , що я шукав останні 30 хвилин. Дуже дякую!
Geert Schuring

Якщо ваше ім'я користувача / пароль містять спеціальні символи, я вважаю, що вам потрібно буде їх перекодувати. Тоді у фрагменті коду вище ви спочатку пройдете url.getUserInfo()thorugh URLDecoder.decode()(@Peter Rader).
m01

Дякую, але для android ви повинні використовувати Base64 наступним чином: String basicAuth = "Basic" + Base64.encodeToString (url.getUserInfo (). GetBytes (), Base64.DEFAULT); httpConn.setRequestProperty ("Авторизація", basicAuth);
валерибодак

Дякую валерібодаку за те доповнення!
javabeangrinder

8

Оскільки я завітав сюди шукати Android-Java-відповідь, я збираюся зробити короткий підсумок:

  1. Використовуйте java.net.Authenticator, як показав Джеймс ван Хуйс
  2. Використовуйте HTTP-клієнт Apache Commons , як у цьому відповіді
  3. Використовуйте базовий java.net.URLConnection та встановіть Заголовк аутентифікації вручну, як показано тут

Якщо ви хочете використовувати java.net.URLCзв’язок із базовою автентифікацією в Android, спробуйте цей код:

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
Дякую. Шукав конкретну відповідь для Android!
Стівен Маккормік

5

Встановити auth за допомогою HttpsURLConnection

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

деякі зміни, отримані з цієї публікації. а Base64 - з пакету java.util.


3

Будьте дуже обережні з підходом "Base64 (). Encode ()", і моя команда отримала 400 помилкових запитів Apache, оскільки це додає \ r \ n в кінці створеного рядка.

Ми виявили, що це нюхає пакети завдяки Wireshark.

Ось наше рішення:

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

Сподіваюся, це допомагає!


3

Використовуйте цей код для основної автентифікації.

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

Я хотів би надати відповідь на випадок, коли у вас немає контролю над кодом, який відкриває з'єднання. Як я це робив під час URLClassLoaderзавантаження файлу jar із захищеного паролем сервера.

AuthenticatorРішення буде працювати , але має той недолік , що він перший намагається отримати доступ до сервера без пароля , і тільки після того , як сервер запитує пароль забезпечує один. Це зайвий зворотній пробіг, якщо ви вже знаєте, що серверу потрібен пароль.

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

}

Це реєструє новий протокол, myякий замінюється, httpколи додаються облікові дані. Тому при створенні нового URLClassLoaderпросто замінити httpз myі все в порядку. Я знаю, URLClassLoaderнадає конструктор, який займає, URLStreamHandlerFactoryале ця фабрика не використовується, якщо URL-адреса вказує на файл jar.


1

З Java 9 ви можете це зробити

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()методу.
WesternGun

0

ІНДРЕМАЦІЯ ANDROD Повний метод запиту даних / відповіді рядка від веб-сервісу із запитом авторизації з ім'ям користувача та паролем

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

Я зробив це так, що вам потрібно це зробити, просто скопіюйте вставити це бути щасливим

    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();
    }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.