我正在使用JBoss 6.1,我得到了一个安全的EJB,其中的方法用@RolesAllowed("Admin")
注释。我试图用Arquillian测试这个方法。
我已在测试的@Before
中成功完成了EJB登录,但是,它无法调用该方法。从TRACE日志中,我可以看到主体和角色是正确的(在本例中为'myuser'
和'Admin'
),但安全EJB的方法信息是错误的(requiredRoles
为空)
TRACE [org.jboss.security.plugins.authorization.JBossAuthorizationContext] Control flag for entry:org.jboss.security.authorization.config.AuthorizationModuleEntry{org.jboss.security.authorization.modules.DelegatingAuthorizationModule:{}REQUIRED}is:[REQUIRED]
TRACE [org.jboss.security.authorization.modules.ejb.EJBPolicyModuleDelegate] method=public au.com.domain.DTOObject au.com.ejb.SecureServiceBean.save(au.com.domain.DTOObject), interface=Local, requiredRoles=Roles()
TRACE [org.jboss.security.authorization.modules.ejb.EJBPolicyModuleDelegate] Exception:Insufficient method permissions, principal=myuser, ejbName=SecureServiceBean, method=save, interface=Local, requiredRoles=Roles(), principalRoles=Roles(Admin,)
我能够使用@PermitAll
在同一个EJB中成功调用一个方法。
我已经查找了有关安全EJB的Arquillian文档,但找不到任何文档。
非常感谢你的帮助。
- Linh
答案 0 :(得分:2)
在JBoss中,如果您未在<security-domain>
中设置jboss.xml
值,则不会在EJB3 bean上启用安全系统。这是一个reminder for JBoss7,它也与JBoss 6.1相关。
另一种选择是在EJB3 bean上使用专有的注释@org.jboss.ejb3.annotation.SecurityDomain
和正确的域值。
根据this forum thread,在WAR文件中部署EJB时需要部署描述符WEB-INF/jboss-ejb3.xml
,这是一个示例:
<?xml version="1.0"?>
<jboss:ejb-jar
xmlns:jboss="http://www.jboss.com/xml/ns/javaee"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:s="urn:security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.jboss.com/xml/ns/javaee http://www.jboss.org/j2ee/schema/jboss-ejb3-2_0.xsd http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_1.xsd"
version="3.1"
impl-version="2.0">
<assembly-descriptor>
<s:security>
<ejb-name>*</ejb-name>
<s:security-domain>yourSecurityDomain</s:security-domain>
</s:security>
</assembly-descriptor>
</jboss:ejb-jar>
答案 1 :(得分:1)
感谢Yves Martin提出的建议。我已经尝试按照你的建议添加了jboss.xml和ejb-jar.xml,遗憾的是它没有用。
我一次又一次地检查了代码,最后我找到了解决这个问题的方法。我的原始代码设置如下:
ObjectRepository接口:
public interface ObjectRepository<T extends DomainObject>
{
public T save(T object);
...
}
TaskServiceBeanLocal接口:
@Local
public interface TaskServiceBeanLocal extends ObjectRepository<Task>
{
}
任务EJB:
@Stateless
@LocalBinding(jndiBinding = TaskServiceBean.LOOKUP_STRING)
@SecurityDomain(value = Security.DOMAIN)
@DeclareRoles({ Roles.ADMIN, Roles.CLERK, Roles.READ_ONLY })
//By default, allow no one access, we'll enable access at the method level
@RolesAllowed({})
public class TaskServiceBean implements TaskServiceBeanLocal
{
public static final String LOOKUP_STRING = "TaskServiceBean/local";
@RolesAllowed({ Roles.ADMIN, Roles.CLERK })
@TransactionAttribute(TransactionAttributeType.REQUIRED)
@Override
public Task save(Task task)
{
...
}
}
Arquillian无法使用问题中的错误访问TaskServiceBean.save()方法:
TRACE [org.jboss.security.authorization.modules.ejb.EJBPolicyModuleDelegate] Exception:Insufficient method permissions, principal=myuser, ejbName=SecureServiceBean, method=save, interface=Local, requiredRoles=Roles(), principalRoles=Roles(Admin,)
从TRACE日志记录中,requiredRoles()由于未知原因而为空。我通过对TaskServiceBeanLocal和具有相同权限的TaskServiceBean实现不同的方法来测试:
@Local
public interface TaskServiceBeanLocal extends ObjectRepository<Task>
{
public void test();
}
//and implement the test() method, having the same permission as the save() method.
public class TaskServiceBean implements TaskServiceBeanLocal
{
@RolesAllowed({ Roles.ADMIN, Roles.CLERK })
@TransactionAttribute(TransactionAttributeType.REQUIRED)
@Override
public Task save(Task task)
{
...
}
@RolesAllowed({ Roles.ADMIN, Roles.CLERK })
@TransactionAttribute(TransactionAttributeType.REQUIRED)
@Override
public void test()
{
System.out.println("hello");
}
}
令我惊讶的是,测试test()方法是成功的。然后我重新声明接口中的save()方法:
@Local
public interface TaskServiceBeanLocal extends ObjectRepository<Task>
{
public Task save(Task object);
public void test();
}
现在,测试save()方法是成功的。在TRACE日志记录语句中,我可以看到我的requiredRoles完全填充在方法签名中。
13:44:35,399 TRACE [org.jboss.security.authorization.modules.ejb.EJBPolicyModuleDelegate] method=public au.com.infomedix.harvey.humantask.domain.Task au.com.infomedix.harvey.ejb.TaskServiceBean.save(au.com.infomedix.harvey.humantask.domain.Task), interface=Local, requiredRoles=Roles(Clerk,Admin,)
我的猜测是,Arquillian没有为通用方法签名注入安全信息,但说实话,我并不完全理解。
无论如何,重新声明接口中的方法可以解决问题。 Arquillian现在可以访问我的安全EJB。感谢大家的宝贵意见。
- Linh