【问题标题】:JMockIt security exception signer information does not matchJMockIt 安全异常签名者信息不匹配
【发布时间】:2013-08-12 23:57:40
【问题描述】:

当运行 JMockIt 并尝试在 testng 中模拟从签名 jar 加载的实例时,出现如下错误(在本例中为码头服务器):

FAILED CONFIGURATION: @BeforeClass startServer
java.lang.SecurityException: class "javax.servlet.FilterRegistration"'s signer information does not match signer information of other classes in the same package
    at java.lang.ClassLoader.checkCerts(ClassLoader.java:943)
    at java.lang.ClassLoader.preDefineClass(ClassLoader.java:657)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:785)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:449)
    at java.net.URLClassLoader.access$100(URLClassLoader.java:71)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    ...

pom 中的依赖顺序是正确的,没有 mock,测试运行良好。所以Java SecurityException: signer information does not match 的提示在这里没有帮助。

有解决办法吗?


这是一个示例测试,应该会产生错误。在这种情况下,我们启动一个完整的容器进行集成测试:

public class MyServletTest {
    private final Server server = new Server(PORT);
    private MockUp<OpenIDAuthenticationProvider> openIDap;

    @BeforeClass
    public void startServer() throws Exception {
        final ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
        context.setContextPath("/");
        context.addServlet(MyServlet.class, "/my/*");
        this.server.setHandler(context);
        this.server.start();
        this.openIDap = new MockUp<OpenIDAuthenticationProvider>() {
            @Mock
            void $init(final UserDAO userDao) {}
        };
    }

    @Test
    ...
}

从 MyServlet 中调用 OpenIDAuthenticationProvider 并在启动期间进行实例化,尽管我不确定这是否重要。

pom.xml 中的对应部分如下所示:

<dependencies>
    <dependency>
        <groupId>org.eclipse.jetty</groupId>
        <artifactId>jetty-servlet</artifactId>
        <version>9.0.3.v20130506</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.eclipse.jetty</groupId>
        <artifactId>jetty-server</artifactId>
        <version>9.0.3.v20130506</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>servlet-api</artifactId>
        <version>2.5</version>
        <scope>provided</scope>
    </dependency>
</dependencies>

【问题讨论】:

  • 你能展示一个重现异常的测试吗?或者在类路径中有任何签名的 jar 就足够了,同时运行一个模拟 jar 中的类的测试?
  • 我猜任何包含检查签名的组件的 jar 都会导致这个问题。
  • 我在测试中使用了上面的代码(测试类和 pom.xml 片段),但没有错误。此外,OpenIDAuthenticationProvider 来自 Spring Security,但上面不包含此依赖项。这同样适用于来自另一个 Jetty 依赖项的 FilterRegistration 接口。如果您愿意,请在 JMockit 问题跟踪器中打开一个新问题,并提供更完整的信息。
  • 其实不是,OpenIDAuthenticationProvider 是我们自定义的实现,我们项目中没有使用spring。 javax.servlet.FilterRegistration 是 javax.servlet api 的一部分,定义在 jetty 实例下方。感谢您的提议,但我实际上更喜欢下面的修复,因为不仅 JMockIt 会影响签名,这只是发生这种情况的一种情况。
  • 我猜你为什么没有得到异常可能是因为春天 OpenIDAuthenicationProvider 有一个空的默认构造函数,这就是为什么用另一个空的构造函数来模拟它可能不会修改生成的 jar 签名。我们的实现在构造函数中做了一些事情,因此模拟是可以注册的更改。

标签: java testing certificate jmockit securityexception


【解决方案1】:

一种方法是使用 JMockIt 停用证书检查。由于 JMockIt(和其他 Mocking 框架)通过检测工作,因此可以修改任何类。下面是一个关于如何模拟导致问题的 ClassLoader 部分的示例:

@BeforeSuite
public void deactivateCertChecker() {
    new MockUp<ClassLoader>() {
        @Mock
        void checkCerts(final String name, final CodeSource cs) {}
    };
}

但请注意,这并不是对实际运行存在签名问题的程序的修复,因为该效果仅在测试运行期间可用,此时已检测到模拟。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-02-11
    • 1970-01-01
    • 1970-01-01
    • 2011-02-22
    • 1970-01-01
    • 1970-01-01
    • 2014-08-14
    相关资源
    最近更新 更多