【问题标题】:Bouncycastle cannot load when I redeploy application当我重新部署应用程序时,Bouncycastle 无法加载
【发布时间】:2012-05-09 22:09:43
【问题描述】:

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

编辑:

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

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

【问题讨论】:

  • 您提供的链接提供了两种方法,您使用的是哪一种?
  • 我将它们都添加到 java.security 这个提供者中,然后在我的类中我注册了这个提供者: static { Security.addProvider(new BouncyCastleProvider()); }
  • 可以只用静态方法试试吗?
  • 是的,我先试试这个,它只适用于 JUnit 测试。但是当我将此应用程序部署到 weblogic 时,它会停止工作,然后我找到上面的链接并按照说明进行操作
  • 一些想法:检查 addProvider() 的返回值,调用 getProviders() 看是否存在,如果可以,在 removeProvider() 处设置断点。

标签: java bouncycastle


【解决方案1】:

您可能收到了NoClassDefFoundError。这是 JSSE 实现的一个已知问题。

这是场景:

  • 您的容器在特定于应用程序的 ClassLoader 中加载充气城堡类
  • 您创建的提供程序实例依赖于该类等该 ClassLoader
  • 然后通过顶级 JVM ClassLoader 中的静态字段将提供程序注册到 JRE API
  • 重新部署时,容器丢弃应用程序 ClassLoader 以创建新的
  • 由于算法已知,第二个提供程序插入失败
  • 使用该算法时,提供程序实例根本无法使用,因为 ClassLoader 已被丢弃
  • 那么唯一的选择就是重启容器来解决问题。

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

避免该问题的推荐方法是在 JVM ClassPath 或容器 ClassPath 中添加充气城堡类。您必须将其从您的应用程序中删除。现在您需要使用静态初始化程序的替代选项注册 BC 提供程序。 WebLogic提供ways to trigger code at server startup(我用过服务器启动类),这段代码将负责为整个服务器/JVM生命周期注册JSSE提供者。

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

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

【讨论】:

  • 我遇到了完全相同的问题,而 Yves 的回答正是解决了它。
  • 嗯非常好的答案。我会试一试,但真的很难测试,因为这个问题在重新部署的时候只发生过几次。你知道为什么有时会出现这个问题吗?但我相信 A. R. Younce 并认为这个答案是正确的。非常感谢
  • 当我第一次遇到多年前的麻烦时,每次重新部署都会失败。可能 WebLogic 已经过改进,能够解决该问题。这主要取决于是否有效地使用了 BC,或者所有必需的类是否已至少加载/实例化一次,或者在重新部署后缺少一些类,如这里 forums.oracle.com/forums/thread.jspa?threadID=2139251
  • 谢谢,复制了 jre/lib/ext 中的 lib,并在 jre/lib/security/java.security 中添加了 security.provider.N=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 才能在重新部署后再次使用它。

【讨论】:

  • 在 Web 应用程序关闭过程中删除 BC 提供程序非常有效!
  • 在关闭期间移除提供程序时,可以从BouncyCastleProvider.PROVIDER_NAME 检索提供程序名称。
【解决方案3】:

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

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

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

Providers.endThreadProviderList(this.oldList);

【讨论】:

  • 这似乎不起作用(我得到了一个No installed provider supports this key:),据我从 JavaDoc 中了解到,它只能由 JAR 验证器在内部使用,而不是 JCE 提供程序的一般用途。跨度>
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-15
  • 2017-03-25
  • 1970-01-01
  • 1970-01-01
  • 2016-07-10
相关资源
最近更新 更多