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