Можно ли отключить Java "единый вход" (использовать учетные данные из "Диспетчера учетных данных" ) в Windows?

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

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

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

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

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

Ответы

Ответ 1

Я искал то же самое, о чем вы просите. До сих пор я не нашел способ 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 code. Из документа :

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

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

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

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

Ответ 2

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

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

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

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

Ответ 3

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