java 重新部署应用程序时无法加载 Bouncycastle

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10379799/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 00:46:42  来源:igfitidea点击:

Bouncycastle cannot load when I redeploy application

javabouncycastle

提问by hudi

I follow this instruction to add bouncycastle: http://www.bouncycastle.org/wiki/display/JA1/Provider+Installationbut I have still one problem. Sometimes when I redeploy my application this provider isnt found so then my application throw exception. This problem occurs just one per 100 redeploy (maybe less). When I restart my server - weblogic then it start working again. I will be very grateful for any advice why this problem occurs

我按照以下说明添加 bouncycastle:http: //www.bouncycastle.org/wiki/display/JA1/Provider+Installation但我仍然有一个问题。有时,当我重新部署我的应用程序时,找不到此提供程序,因此我的应用程序会抛出异常。此问题每 100 次重新部署仅发生一个(可能更少)。当我重新启动服务器时 - weblogic 然后它又开始工作了。对于为什么会出现此问题的任何建议,我将不胜感激

EDIT:

编辑:

I am using both method in link above because when I use just one of them then it doesnt work I add to java.security this provder and then in my class I registered this provder:

我在上面的链接中使用了这两种方法,因为当我只使用其中一种方法时它不起作用我将这个提供者添加到 java.security 然后在我的课程中我注册了这个提供者:

static {
    Security.addProvider(new BouncyCastleProvider());
}

回答by Yves Martin

You probably got a NoClassDefFoundError. This is a known issue with JSSE implementations.

你可能有一个NoClassDefFoundError. 这是 JSSE 实现的一个已知问题。

Here is the scenario:

这是场景:

  • Your container loads bouncy castle classes in an application specific ClassLoader
  • The provider instance you create depends on that classes and so on that ClassLoader
  • Then the provider is registered into JRE API thanks to static fields in top level JVM ClassLoader
  • When redeploying, the container discards the application ClassLoader to create a new one
  • As the algorithm is already known, the second provider insertion fails silently
  • When using the algorithm the provider instance is simply unusable because the ClassLoader has been discarded
  • Then the only option is to restart the container to get the situation fixed.
  • 您的容器在特定于应用程序的 ClassLoader 中加载充气城堡类
  • 您创建的提供程序实例取决于该类,依此类推 ClassLoader
  • 然后,由于顶级 JVM ClassLoader 中的静态字段,提供程序被注册到 JRE API 中
  • 重新部署时,容器丢弃应用类加载器创建一个新的
  • 由于算法已知,第二次提供者插入失败无提示
  • 使用该算法时,提供者实例根本无法使用,因为 ClassLoader 已被丢弃
  • 然后唯一的选择是重新启动容器以修复这种情况。

As there is no standard listener for the undeploy event, it is not possible to trigger the JSSE provider removal at time.

由于 undeploy 事件没有标准侦听器,因此无法及时触发 JSSE 提供程序移除。

The recommended way to avoid that trouble is to have bouncy castle classes in your JVM ClassPath or in your container ClassPath. You have to remove it from your application. Now you need to register BC provider with an alternate option to the static initializer. WebLogic provides ways to trigger code at server startup(I have used server startup class), this code will be responsible to register JSSE providers for the whole server/JVM lifetime.

避免这种麻烦的推荐方法是在 JVM ClassPath 或容器 ClassPath 中使用充气城堡类。您必须将其从您的应用程序中删除。现在您需要使用静态初始化程序的替代选项注册 BC 提供程序。WebLogic 提供了在服务器启动时触发代码的方法(我使用了服务器启动类),该代码将负责为整个服务器/JVM 生命周期注册 JSSE 提供程序。

An alternate option is to add the following line in JRE java.securityfile with bouncy castle jar in jre/lib/extbut I do not like that way because it may be lost when updating: security.provider.7=org.bouncycastle.jce.provider.BouncyCastleProvider

另一种选择是在java.security带有充气城堡 jar 的JRE文件中添加以下行,jre/lib/ext但我不喜欢这种方式,因为更新时它可能会丢失:security.provider.7=org.bouncycastle.jce.provider.BouncyCastleProvider

So then the application simply expects implementations are there, it may be a good idea to add tests for algorithm availability to report any troubles to operators and users.

因此,应用程序只是期望实现在那里,添加算法可用性测试以向操作员和用户报告任何问题可能是个好主意。

回答by Gugelhupf

I use this work around for redeploy the application in Tomcat :

我使用此解决方法在 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 );
    }
}
.
.
.
}

The interesting thing is I have to remove the BouncyCastleProvider first to use it again after redeploy.

有趣的是我必须先删除 BouncyCastleProvider 才能在重新部署后再次使用它。

回答by Hans-Joachim Kliemeck

this issue could easily be solved by the following code and usage of the sun.security.jce package:

这个问题可以通过以下代码和 sun.security.jce 包的用法轻松解决:

ProviderList list = Providers.getFullProviderList();
ProviderList.add(list, new BouncyCastleProvider());
Providers.beginThreadProviderList(list);

the list will be extended to use the bouncy castle provider and the new list will be injected as a thread local. this could be used inside a servletfilter or something else. maybe it is necessary to reset the list to the old value after the request is finished

该列表将被扩展以使用充气城堡提供者,并且新列表将作为线程本地注入。这可以在 servletfilter 或其他东西中使用。也许有必要在请求完成后将列表重置为旧值

Providers.endThreadProviderList(this.oldList);