Можно ли отключить «единый вход» Java (использовать учетные данные из «Диспетчера учетных данных») в Windows? - PullRequest
14 голосов
/ 31 мая 2011

Страница Oracle "Аутентификация Http" из документации по Java SE 6 гласит, что "если вы работаете на компьютере Windows как пользователь домена или вы работаете на компьютере Linux или Solaris, который имеетуже выполнил команду kinit и получил кэш учетных данных ", тогда экземпляр, переданный Authenticator.setDefault()", будет полностью проигнорирован ".

Это соответствует тому, что я наблюдал: настройка HTTPили HTTPS-соединение в системе Windows с хостом X всегда передает учетные данные для хоста X из «Учетных данных Windows» в «Хранилище Windows», как показано на моей странице панели управления Windows 7 «Диспетчер учетных данных».

Однако , в моем случае я не хочу использовать какие-либо учетные данные, которые могут храниться в Windows, но вместо этого я всегда хочу использовать учетные данные, которые я явно указываю в коде.

Isесть способ переопределить задокументированное поведение, т. е. есть ли способ игнорировать учетные данные, хранящиеся в Windows?

Обновление: Если нет, можетКто-нибудь указывает мне место в исходном коде Java SE 6, где я вижу, что сохраненные учетные данные Windows нельзя игнорировать?

Ответы [ 4 ]

6 голосов
/ 05 февраля 2013

По крайней мере в Java 7 есть класс с именем sun.net.www.protocol.http.ntlm.NTLMAuthenticationCallback, который, кажется, помогает в этой ситуации.Единый вход вызывается только для «доверенных» URL-адресов.

Вот простейшая реализация для его отключения (вызов этого инициализатора перед открытием соединения HTTP):

static {
    NTLMAuthenticationCallback.setNTLMAuthenticationCallback(new NTLMAuthenticationCallback()
    {
        @Override
        public boolean isTrustedSite(URL url)
        {
            return false;
        }
    });
}

Я предполагаю, что реализация по умолчанию - доверять всему: (

6 голосов
/ 27 января 2012

Я искал то же, что вы просите. До сих пор я не нашел в JDK способа сделать это.

Существует запрос на улучшение базы данных ошибок Java. Взгляните на отчет , чтобы узнать, получит ли он ответ от Sun (проголосуйте за отчет, так что, надеюсь, это скоро исправят).

То, что я закончил, было переопределено sun.net.www.protocol.http.NTLMAuthentication классом. Посмотрев на sun.net.www.protocol.http.HttpURLAuthentication, я обнаружил, что единственное, что вам нужно изменить, это результат:

NTLMAuthentication.supportsTransparentAuth()

Этот метод имеет жестко возвращаемое значение, true на платформах Windows и false в противном случае. Этот код извлечен из JDK, установленного в Windows 7:

static boolean supportsTransparentAuth()
{
  return true;
}

Этот метод сообщает, должны ли учетные данные Windows использоваться по умолчанию. Если установлено значение true, , пользовательский код аутентификатора не будет называться . Смотрите этот фрагмент HttpURLConnection класса:

//Declared as a member variable of HttpURLConnection
private boolean tryTransparentNTLMServer = NTLMAuthentication.supportsTransparentAuth();

//Inside of getServerAuthentication method.
PasswordAuthentication a = null;
if (!tryTransparentNTLMServer) {
    //If set to false, this will call Authenticator.requestPasswordAuthentication().
    a = privilegedRequestPasswordAuthentication(url.getHost(), addr, port, url.getProtocol(), "", scheme, url, RequestorType.SERVER);
}

/* If we are not trying transparent authentication then 
* we need to have a PasswordAuthentication instance. For
* transparent authentication (Windows only) the username 
* and password will be picked up from the current logged 
* on users credentials.
*/
if (tryTransparentNTLMServer || (!tryTransparentNTLMServer && a != null)) {
    //If set to true or if Authenticator did not return any credentials, use Windows credentials.
    //NTLMAuthentication constructor, if receives a == null will fetch current looged user credentials.
    ret = new NTLMAuthentication(false, url1, a);
}

Чтобы получить NTLMAuthentication исходный код, я использовал этот Java-декомпилятор . Открыл rt.jar, расположенный в папке установки JDK, и скопировал нужный код класса.

Затем я просто изменил supportsTransparentAuth, чтобы вернуть false. Однако было бы очень желательно, чтобы этот метод сначала проверял системное свойство, а затем возвращал true или false на основании этого.

Для компиляции я просто поместил java-файл в структуру папок sun / net / www / protocol / http и запустил:

javac NTLMAuthentication.java

Затем запустите мое приложение, используя:

java -Xbootclasspath:"path/to/your/sun/net/www/protocol/http/classes;normal/JDK/boot/directories"

Это скажет JVM загрузить нашу реализацию NTLMAuthentication перед той, что в rt.jar. Вы должны быть осторожны, чтобы не пропустить пути загрузки классов по умолчанию с -Xbootclasspath, иначе будут ClassNotFound ошибки.

После этого все работало просто отлично.

У этого подхода есть важные недостатки, о которых вам следует знать.

  • Существуют угрозы безопасности. Любой может оставить другой файл .class в вашей загрузочной папке и украсть учетные данные пользователя или другую важную информацию.
  • Код из пакетов Sun может быть изменен без уведомления и поэтому может быть несовместим с вашими изменениями.
  • Если вы развернете этот код, вы нарушите лицензию на использование кода Sun. Из документации :

-Xbootclasspath: bootclasspath Укажите разделенный точкой с запятой список каталогов, JAR-архивов и ZIP-архивов для поиска загрузочного класса. файлы. Они используются вместо файлов загрузочных классов, включенных в Java 2 SDK. Примечание. Приложения, использующие этот параметр для переопределение класса в rt.jar не должно быть развернуто, так как это противоречат лицензии на двоичный код Java 2 Runtime Environment.

Итак, это определенно не подходит для производственных сред.

Наконец, это отличный источник информации о параметре пути загрузочного класса и загрузчиках классов Java: PDF

Надеюсь, это поможет.

2 голосов
/ 04 апреля 2013

Кажется, что класс sun.net.www.protocol.http.ntlm.NTLMAuthenticationCallback был добавлен в исправление 24+ для java 6.0, поэтому предлагаемое решение может работать и в java 6.0. Смотрите ссылку в следующем посте: http://www.mail-archive.com/users@cxf.apache.org/msg22897.html

0 голосов
/ 21 мая 2019

В Java v8 212 или выше, «прозрачная» аутентификация SSO через NTLMv2 по умолчанию отключена, как следствие этого CVE: https://nvd.nist.gov/vuln/detail/CVE-2019-2426. Для получения дополнительной информации: Как обеспечить аутентификацию ntlm при вызове любого URL?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...