Используйте Arquillian для тестирования защищенного EJB

Я использую JBoss 6.1, и у меня есть безопасный EJB с методами, аннотированными @RolesAllowed("Admin"). Я пытаюсь проверить этот метод с помощью Arquillian.

Я успешно выполнил регистрацию EJB в @Before теста, однако мне не удалось вызвать метод. Из журнала 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,)

Мне удалось успешно вызвать метод в том же EJB с помощью @PermitAll.

Я искал документацию Arquillian по безопасному EJB, но ничего не нашел.

Большое спасибо за вашу помощь.

-- Линь


person Linh    schedule 10.11.2011    source источник
comment
Не могли бы вы опубликовать код вашего теста?   -  person Andre Rodrigues    schedule 25.01.2012


Ответы (2)


В JBoss система безопасности не включается для bean-компонентов EJB3, если вы не установили значение <security-domain> в jboss.xml. Вот напоминание для JBoss7, и оно также актуально для JBoss 6.1.

Альтернативный вариант — использовать проприетарную аннотацию @org.jboss.ejb3.annotation.SecurityDomain с правильным значением домена для ваших компонентов EJB3.

Согласно этой ветке форума, дескриптор развертывания WEB-INF/jboss-ejb3.xml требуется при развертывании EJB в WAR, и вот пример для него:

<?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>
person Yves Martin    schedule 25.01.2012
comment
@Erica, если ответ недостаточно хорош, опубликуйте журналы и код, чтобы помочь в диагностике - person Yves Martin; 30.01.2012
comment
Я попросил оригинального автора для более подробной информации. Тем не менее, домен безопасности требуется для всей безопасности JBoss, и я считаю, что безопасность работает должным образом во всех ситуациях, кроме при доступе через arquillian. - person Erica; 31.01.2012

Спасибо Ив Мартин за предложение. Я попытался добавить jboss.xml и ejb-jar.xml, как вы предложили, но, к сожалению, это не сработало.

Я снова и снова просматривал код и, наконец, нашел решение этой проблемы. Моя исходная настройка кода выглядит следующим образом:

Интерфейс объектного репозитория:

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 я вижу, что мои требуемые роли полностью заполнены в сигнатуре метода.

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. Спасибо всем за ваш ценный вклад.

-- Линь

person Linh    schedule 08.02.2012