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


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

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

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

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

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

3 14

3 ответа:

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

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

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

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

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

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

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

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

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

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

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

Кажется, что класс солнце.чистая.ВСП.протокол.протоколу HTTP.протокол NTLM.NTLMAuthenticationCallback была добавлена к Java 6.0 патч 24+, так что предложенное решение может работать в Java 6.0, а также. Смотрите ссылку в следующем посте: http://www.mail-archive.com/users@cxf.apache.org/msg22897.html