Bouncycastle не может загружаться при перераспределении приложения
Я следую этой инструкции, чтобы добавить bouncycastle:
http://www.bouncycastle.org/wiki/display/JA1/Provider+Installation
но у меня есть еще одна проблема. Иногда, когда я повторно развертываю свое приложение, этот провайдер не найден, поэтому мое приложение исключает исключение. Эта проблема возникает только один раз за 100 перераспределений (может быть, меньше). Когда я перезапускаю свой сервер - weblogic, он начинает работать снова. Я буду очень благодарен за любой совет, почему возникла эта проблема.
EDIT:
Я использую оба метода в ссылке выше, потому что, когда я использую только один из них, он не работает
Я добавляю в java.security этот прорыв, а затем в своем классе я зарегистрировал этот прорыв:
static {
Security.addProvider(new BouncyCastleProvider());
}
Ответы
Ответ 1
Вероятно, вы получили NoClassDefFoundError
. Это известная проблема с реализациями JSSE.
Вот сценарий:
- В вашем контейнере загружаются классные классы замков в классе ClassLoader, специфичном для приложения.
- Созданный экземпляр поставщика зависит от этих классов и так далее, что ClassLoader
- Затем провайдер зарегистрирован в JRE API благодаря статическим полям верхнего уровня JVM ClassLoader
- При повторном развертывании контейнер отбрасывает приложение ClassLoader для создания нового
- Поскольку алгоритм уже известен, вторая вставка провайдера терпит неудачу
- При использовании алгоритма экземпляр провайдера просто неприменим, поскольку ClassLoader был отброшен
- Тогда единственный вариант - перезагрузить контейнер, чтобы ситуация была исправлена.
Поскольку нет стандартного прослушивателя для события undeploy, невозможно запустить удаление провайдера JSSE вовремя.
Рекомендуемый способ избежать этой проблемы состоит в том, чтобы иметь классные классы замка в JVM ClassPath или в вашем контейнере ClassPath. Вы должны удалить его из своего приложения. Теперь вам нужно зарегистрировать поставщика BC с альтернативной опцией статического инициализатора. WebLogic предоставляет способы запуска кода при запуске сервера (я использовал класс запуска сервера), этот код будет отвечать за регистрацию поставщиков JSSE для всего сервера /JVM.
Альтернативный вариант заключается в том, чтобы добавить следующую строку в файл JRE java.security
с баком jown в стиле jre/lib/ext
, но мне это не нравится, потому что он может быть потерян при обновлении: security.provider.7=org.bouncycastle.jce.provider.BouncyCastleProvider
Итак, тогда приложение просто ожидает, что реализации есть, может быть хорошей идеей добавить тесты на доступность алгоритма, чтобы сообщать о любых проблемах операторам и пользователям.
Ответ 2
Я использую эту работу для повторного развертывания приложения в Tomcat:
public class GenSignCastle {
BouncyCastleProvider bcProvider = null;
public GenSignCastle() {
if ( bcProvider == null ) {
bcProvider = new BouncyCastleProvider();
Provider[] providers = Security.getProviders();
String name = bcProvider.getName();
Security.removeProvider( name ); // remove old instance
Security.addProvider( bcProvider );
}
}
.
.
.
}
Интересно, что мне нужно сначала удалить BouncyCastleProvider, чтобы использовать его снова после повторного развертывания.
Ответ 3
эта проблема может быть легко решена с помощью следующего кода и использования пакета sun.security.jce:
ProviderList list = Providers.getFullProviderList();
ProviderList.add(list, new BouncyCastleProvider());
Providers.beginThreadProviderList(list);
список будет расширен, чтобы использовать провайдера bouncy castle, а новый список будет введен как поток. это может быть использовано внутри сервлетфильтра или что-то еще. возможно, необходимо, чтобы reset список к старому значению после завершения запроса
Providers.endThreadProviderList(this.oldList);