Подключение к удаленному URL-адресу, требующему аутентификации с использованием Java


125

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

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

Проверьте здесь: stackoverflow.com/questions/1359689/...
WesternGun

Ответы:


134

Вы можете установить аутентификатор по умолчанию для HTTP-запросов следующим образом:

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

Кроме того, если вам требуется большая гибкость, вы можете проверить Apache HttpClient , который предоставит вам больше возможностей аутентификации (а также поддержку сеансов и т. Д.)


4
Как вы справляетесь с ошибкой аутентификации? [Например, если пользователь предоставляет учетные данные для аутентификации имени пользователя и пароля, которые не совпадают ни с чем]?
SK9,

2
Приведенный выше код работает, но совершенно не подразумевает, что происходит. Там происходит подклассификация и переопределение методов, покопайтесь в документации по этим классам, если хотите знать, что происходит. Код здесь более явные javacodegeeks
Fuchida

12
Можно ли установить конкретный вызов для Authenticatorконкретного URL.openConnection()вызова, а не глобально?
Юрий Наконечный

@ Юра: нет. Он должен быть глобальным. Однако вы можете делать злые вещи, такие как установка глобального аутентификатора, который извлекает учетные данные из локальных переменных потока и устанавливает учетные данные для каждого потока перед установкой HTTP-соединения.
Дэвид Гивен

4
В ответ на @YuriyNakonechnyy ... если вы используете Java 9 или выше, вы можете позвонить HttpURLConnection.setAuthenticator(). К сожалению, в Java 8 и более ранних версиях экземпляр Authenticator является глобальной переменной JVM. См .: docs.oracle.com/javase/9/docs/api/java/net/…
Нил Бартлетт,

134

Есть собственная и менее навязчивая альтернатива, которая работает только для вашего звонка.

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.
Мэтью Баккет,

Это не сработало для меня ... Только то, как @James Van Huis был хорош
Мигель Рибейро

Это «родной» для Grails и многих других фреймворков Java, потому что все они используют библиотеки Apache Commons.
Вандерсон Сантос,

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

Обратите внимание в комментарии от valerybodak ниже, как это делается в среде разработки Android.


1
Это было именно то , что я искал последние 30 минут. Большое спасибо!
Герт Шуринг

Если ваше имя пользователя / пароль содержит специальные символы, я считаю, что вам нужно будет их закодировать. Затем, во фрагменте кода выше, вы должны пройти url.getUserInfo()Копание URLDecoder.decode()первый (@Peter Rader).
m01

Спасибо, но для Android вы должны использовать Base64 следующим образом: String basicAuth = "Basic" + Base64.encodeToString (url.getUserInfo (). GetBytes (), Base64.DEFAULT); httpConn.setRequestProperty («Авторизация», basicAuth);
валерибодак

Спасибо valerybodak за такой комплимент!
javabeangrinder

8

Поскольку я пришел сюда в поисках ответа на Android-Java, я сделаю краткое резюме:

  1. Используйте java.net.Authenticator, как показано Джеймсом ван Хуисом
  2. Используйте HTTP-клиент Apache Commons , как в этом ответе
  3. Используйте базовый java.net.URLConnection и установите Authentication-Header вручную, как показано здесь

Если вы хотите использовать java.net.URLConnection с базовой аутентификацией в 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

Удалось установить аутентификацию с помощью 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.