4

我的环境是 Jboss AS 7.1.0。我正在使用 JUnit 和 Arquillian 进行单元测试。我的 ejb 中有使用 getUserPrincipal() 和 isCallerInRole() 方法的 SSB。为了对这些 ejb 方法进行单元测试,我必须从单元测试用例模拟登录,然后调用 ejb。

这是我正在尝试测试的 EJB 方法的示例:

@RolesAllowed({"user","admin"})
public User getMyUserDetails() throws BadInputDataException {
    String userName = ctx.getCallerPrincipal().getName();
    return findUser(userName);
}

如何编写 JUnit 测试用例来测试此方法?我提前感谢您的帮助。

07/19 更新(基于以下 Tair 的解决方案)

我的安全域配置如下:

<security-domains>
    <security-domain name="other" cache-type="default">
         <authentication>
             <login-module code="Remoting" flag="optional">
                 <module-option name="password-stacking" value="useFirstPass"/>
             </login-module>
             <login-module code="Database" flag="required">
                 <module-option name="dsJndiName" value="java:jboss/datasources/MysqlDS"/>
                 <module-option name="principalsQuery" value="select Password from Principals where PrincipalID=?"/>
                 <module-option name="rolesQuery" value="select Role, RoleGroup from Roles where PrincipalID=?"/>
                 <module-option name="password-stacking" value="useFirstPass"/>
                 <module-option name="hashAlgorithm" value="MD5"/>
                 <module-option name="hashEncoding" value="RFC2617"/>
                 <module-option name="hashUserPassword" value="false"/>
                 <module-option name="hashStorePassword" value="true"/>
                 <module-option name="passwordIsA1Hash" value="true"/>
                 <module-option name="storeDigestCallback" value="org.jboss.security.auth.callback.RFC2617Digest"/>
             </login-module>
         </authentication>
     </security-domain>

我将下面 Tair 解决方案中显示的 JBossLoginConfigFactory 更改为使用 org.jboss.security.auth.spi.DatabaseServerLoginModule。

我已将 JBossLoginConfigFactory 更改为对 DatabaseServerLoginModule 使用以下方法。

private AppConfigurationEntry createDatabaseModuleConfigEntry() {
    Map<String, String> options = new HashMap<String, String>();
    options.put("dsJndiName", "java:jboss/datasources/MysqlDS");
    options.put("hashAlgorithm", "MD5");
    options.put("hashEncoding", "RFC2617");
    options.put("hashUserPassword", "false");
    options.put("hashStorePassword", "true");
    options.put("passwordIsA1Hash", "true");
    options.put("storeDigestCallback", "org.jboss.security.auth.callback.RFC2617Digest");
    options.put("principalsQuery", "select Password from Principals where PrincipalID=?");
    options.put("rolesQuery", "select Role, RoleGroup from Roles where PrincipalID=?");

    return new AppConfigurationEntry("org.jboss.security.auth.spi.DatabaseServerLoginModule",
                AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, options);
}

我正在调用此方法而不是 createUsersRolesLoginModuleConfigEntry()。测试用例中的 loginContext.login() 现在由于以下原因而失败:

Caused by: java.io.WriteAbortedException: writing aborted; java.io.NotSerializableException: org.jboss.security.auth.callback.MapCallback

不知道我现在应该改变什么!

2012 年 7 月 20 日更新:该问题的完整解决方案如下。如果您的解决方案不需要 DatabaseServerLoginModule,只需参考 Tair 回复中的解决方案即可。

就我而言,我将数据库作为 JaaS 身份验证和摘要身份验证。因此,我必须对上面的示例进行以下代码更改。

  1. 我修改了代码(JBossLoginContextFactory)以支持“org.jboss.security.auth.spi.DatabaseServerLoginModule”,如下所示。我在创建 AppConfigurationEntry[] 时调用此方法而不是 createUsersRolesLoginModuleConfigEntry()。

    私有 AppConfigurationEntry createDatabaseModuleConfigEntry() { Map options = new HashMap(); options.put("dsJndiName", "java:jboss/datasources/MysqlDS"); options.put("principalsQuery", "select Password from Principals where PrincipalID=?"); options.put("rolesQuery", "select Role, RoleGroup from Roles where PrincipalID=?"); return new AppConfigurationEntry("org.jboss.security.auth.spi.DatabaseServerLoginModule", AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, options); }

  2. 当我使用摘要身份验证时,我的密码在数据库中被加密。因此,在从我的测试用例中传递密码时,我正在加密并传递密码,如下所示。LoginContext loginContext = JBossLoginContextFactory.createLoginContext("username", md5Hex("my_username"+":"+PropertyManager.getProp("realm")+":"+"my_password"));

现在登录成功了!!

4

1 回答 1

1

本示例涵盖了您的情况。基本上可以归结为:

  1. 使用 arquillianContext 构建具有预设值的 ContextContext.SECURITY_PRINCIPALContext.SECURITY_CREDENTIALS
  2. 使用该上下文获取对您的 EJB 的引用
  3. 测试一下。

祝你好运!

更新:从那时起,Arquillian 似乎发生了很大变化,幸运的是我们有另一个解决方案。我对其进行了测试并确认它有效!

于 2012-07-13T12:35:12.760 回答