Аутентификация JAAS в JMS с использованием WildFly: javax.jms.JMSSecurityException: HQ119032: пользователь: null не имеет разрешения=отправить по адресу {2}

используя WildFly 9.0.2 final, определена в standalone-full.xml следующим образом.

разделы как <address-settings>, <acceptors> и <connectors> полностью опущены, так как я ничего не менял в них.

<hornetq-server>
    <security-domain>ProjectRealm</security-domain>
    <security-enabled>true</security-enabled>
    <journal-file-size>102400</journal-file-size>

    <security-settings>
        <security-setting match="#">
            <permission type="send" roles="ROLE_USER ROLE_ADMIN"/>
            <permission type="consume" roles="ROLE_USER ROLE_ADMIN"/>
            <permission type="createDurableQueue" roles="ROLE_USER ROLE_ADMIN"/>
            <permission type="deleteDurableQueue" roles="ROLE_USER ROLE_ADMIN"/>
            <permission type="createNonDurableQueue" roles="ROLE_USER ROLE_ADMIN"/>
            <permission type="deleteNonDurableQueue" roles="ROLE_USER ROLE_ADMIN"/>
        </security-setting>
    </security-settings>    

    <jms-connection-factories>        
        <connection-factory name="destinationFactory">
            <connectors>
                <connector-ref connector-name="http-connector"/>
            </connectors>
            <entries>
                <entry name="java:jboss/exported/jms/destinationFactory"/>
            </entries>
        </connection-factory>        
    </jms-connection-factories>

    <jms-destinations>        
        <jms-queue name="userStatusQueue">
            <entry name="jms/destination"/>
            <entry name="java:jboss/exported/jms/destination"/>
        </jms-queue>
    </jms-destinations>
</hornetq-server>

он определяет фабрику соединений с именем destinationFactory использует http-connector и очередь с именем userStatusQueue которые привязаны к имени JNDI, как указано во вложенном <entry> элемент.

он также определяет безопасность домен.

<security-domain>ProjectRealm</security-domain>

безопасность включена (по умолчанию) с помощью,

<security-enabled>true</security-enabled>

в этом случае возникает следующее исключение.

15:49:28,093 WARNING [javax.enterprise.resource.webcontainer.jsf.lifecycle] (default task-2) java.lang.RuntimeException: javax.jms.JMSSecurityRuntimeException: HQ119032: User: null doesnt have permission=SEND on address {2}: javax.el.ELException: java.lang.RuntimeException: javax.jms.JMSSecurityRuntimeException: HQ119032: User: null doesnt have permission=SEND on address {2}
    at com.sun.el.parser.AstValue.invoke(AstValue.java:296)
    at com.sun.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:304)
    at org.jboss.weld.util.el.ForwardingMethodExpression.invoke(ForwardingMethodExpression.java:40)
    at org.jboss.weld.el.WeldMethodExpression.invoke(WeldMethodExpression.java:50)
    at org.jboss.weld.util.el.ForwardingMethodExpression.invoke(ForwardingMethodExpression.java:40)
    at org.jboss.weld.el.WeldMethodExpression.invoke(WeldMethodExpression.java:50)
    at javax.faces.event.MethodExpressionActionListener.processAction(MethodExpressionActionListener.java:149)
    at javax.faces.event.ActionEvent.processListener(ActionEvent.java:88)
    at javax.faces.component.UIComponentBase.broadcast(UIComponentBase.java:814)
    at javax.faces.component.UICommand.broadcast(UICommand.java:300)
    at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:790)
    at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1282)
    at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
    at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:198)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:658)
    at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:86)
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:130)
    at org.primefaces.webapp.filter.FileUploadFilter.doFilter(FileUploadFilter.java:78)
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:60)
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:132)
    at io.undertow.websockets.jsr.JsrWebSocketFilter.doFilter(JsrWebSocketFilter.java:151)
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:60)
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:132)
    at org.omnifaces.facesviews.FacesViewsForwardingFilter.filterExtensionLess(FacesViewsForwardingFilter.java:128)
    at org.omnifaces.facesviews.FacesViewsForwardingFilter.doFilter(FacesViewsForwardingFilter.java:89)
    at org.omnifaces.filter.HttpFilter.doFilter(HttpFilter.java:108)
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:60)
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:132)
    at filter.LoginNocacheFilter.doFilter(LoginNocacheFilter.java:32)
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:60)
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:132)
    at org.omnifaces.filter.CharacterEncodingFilter.doFilter(CharacterEncodingFilter.java:122)
    at org.omnifaces.filter.HttpFilter.doFilter(HttpFilter.java:108)
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:60)
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:132)
    at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:85)
    at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
    at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
    at org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:131)
    at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    at io.undertow.security.handlers.AuthenticationConstraintHandler.handleRequest(AuthenticationConstraintHandler.java:51)
    at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
    at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
    at io.undertow.servlet.handlers.security.ServletSecurityConstraintHandler.handleRequest(ServletSecurityConstraintHandler.java:56)
    at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:58)
    at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:72)
    at io.undertow.security.handlers.NotificationReceiverHandler.handleRequest(NotificationReceiverHandler.java:50)
    at io.undertow.security.handlers.SecurityInitialHandler.handleRequest(SecurityInitialHandler.java:76)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    at org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:282)
    at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:261)
    at io.undertow.servlet.handlers.ServletInitialHandler.access0(ServletInitialHandler.java:80)
    at io.undertow.servlet.handlers.ServletInitialHandler.handleRequest(ServletInitialHandler.java:172)
    at io.undertow.server.Connectors.executeRootHandler(Connectors.java:199)
    at io.undertow.server.HttpServerExchange.run(HttpServerExchange.java:774)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.RuntimeException: javax.jms.JMSSecurityRuntimeException: HQ119032: User: null doesnt have permission=SEND on address {2}
    at io.undertow.servlet.spec.RequestDispatcherImpl.forwardImpl(RequestDispatcherImpl.java:219)
    at io.undertow.servlet.spec.RequestDispatcherImpl.forward(RequestDispatcherImpl.java:108)
    at com.sun.faces.context.ExternalContextImpl.dispatch(ExternalContextImpl.java:643)
    at admin.bean.SignInCheck.signIn(SignInCheck.java:63)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at com.sun.el.parser.AstValue.invoke(AstValue.java:292)
    ... 64 more
Caused by: javax.jms.JMSSecurityRuntimeException: HQ119032: User: null doesnt have permission=SEND on address {2}
    at org.hornetq.jms.client.JmsExceptionUtils.convertToRuntimeException(JmsExceptionUtils.java:76)
    at org.hornetq.jms.client.HornetQJMSProducer.send(HornetQJMSProducer.java:112)
    at org.hornetq.jms.client.HornetQJMSProducer.send(HornetQJMSProducer.java:135)
    at filter.SecurityCheck.sendMessageToDestination(SecurityCheck.java:54)
    at filter.SecurityCheck.doAfterProcessing(SecurityCheck.java:107)
    at filter.SecurityCheck.doFilter(SecurityCheck.java:161)
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:60)
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:132)
    at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:85)
    at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
    at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:263)
    at io.undertow.servlet.handlers.ServletInitialHandler.dispatchToPath(ServletInitialHandler.java:198)
    at io.undertow.servlet.spec.RequestDispatcherImpl.forwardImpl(RequestDispatcherImpl.java:195)
    ... 72 more
Caused by: javax.jms.JMSSecurityException: HQ119032: User: null doesnt have permission=SEND on address {2}
    at org.hornetq.core.protocol.core.impl.ChannelImpl.sendBlocking(ChannelImpl.java:399)
    at org.hornetq.core.client.impl.ClientProducerImpl.sendRegularMessage(ClientProducerImpl.java:334)
    at org.hornetq.core.client.impl.ClientProducerImpl.doSend(ClientProducerImpl.java:304)
    at org.hornetq.core.client.impl.ClientProducerImpl.send(ClientProducerImpl.java:135)
    at org.hornetq.jms.client.HornetQMessageProducer.doSendx(HornetQMessageProducer.java:524)
    at org.hornetq.jms.client.HornetQMessageProducer.send(HornetQMessageProducer.java:210)
    at org.hornetq.jms.client.HornetQMessageProducer.send(HornetQMessageProducer.java:200)
    at org.hornetq.jms.client.HornetQJMSProducer.send(HornetQJMSProducer.java:107)
    ... 87 more
Caused by: HornetQSecurityException[errorType=SECURITY_EXCEPTION message=HQ119032: User: null doesnt have permission=SEND on address {2}]
    ... 95 more

сообщение отправляется через определенную очередь (которая принимается управляемым сообщением Bean (MDB)), когда <security-enabled> вынесено false значение. Однако мне нужны только пользователи, у которых есть предопределенные полномочия/роль (ROLE_ADMIN или ROLE_USER), чтобы создать очередь и отправлять сообщения по.

в подход с использованием <security-domain> как показано выше, сбой с вышеуказанным исключением.

я попытался добавить роли в /standalone/configuration/application-roles.properties точно так же, как определено в в

<module-option name="rolesProperties"
               value="file:${jboss.server.config.dir}/ProjectRealm.properties"/>

внутри

admins=ROLE_ADMIN
users=ROLE_USER

что еще нужно сделать для аутентификации пользователей перед отправкой сообщений через очередь?


дополнительные :

менеджер безопасности JAAS использует следующий домен аутентификация и авторизация пользователей с помощью области JDBC (источник данных XA). Это уже работает нормально.

<security-domain name="ProjectRealm" cache-type="default">
    <authentication>
        <login-module code="Database" flag="required">
            <module-option name="dsJndiName" value="java:jboss/datasources/projectXADatasource"/>
            <module-option name="principalsQuery" value="SELECT password FROM user_table WHERE email_id=?"/>
            <module-option name="rolesQuery" value="SELECT user_role, 'Roles' FROM user_roles ur INNER JOIN user_table ut ON ur.user_id=ut.user_id WHERE ut.email_id=?"/>
            <module-option name="hashAlgorithm" value="SHA-256"/>
            <module-option name="hashEncoding" value="hex"/>
            <module-option name="hashCharset" value="UTF-8"/>
            <module-option name="hashStorePassword" value="false"/>
            <module-option name="unauthenticatedIdentity" value="guest"/>
        </login-module>

        <login-module code="RoleMapping" flag="required">
            <module-option name="rolesProperties" value="file:${jboss.server.config.dir}/ProjectRealm.properties"/>
            <module-option name="replaceRole" value="false"/>
        </login-module>
    </authentication>
</security-domain>

очередь вводится в фильтр сервлета аутентификации, который используется JMSContext для отправки сообщения через очередь после успешной аутентификации и авторизации пользователя.

@WebFilter(filterName = "SecurityCheck", urlPatterns = {"/WEB-INF/jaas/*"}, dispatcherTypes = {DispatcherType.FORWARD})
public final class SecurityCheck implements Filter {

    @Resource(lookup = "java:/jms/destination")
    private Queue queue;

    @Inject
    @JMSConnectionFactory("java:jboss/exported/jms/destinationFactory")
    private JMSContext context;
    // jms/destinationFactory is expected to work here but it only works using the fully qualified namespace as above.

    public SecurityCheck() {}

    private void sendMessageToDestination(String message) throws JMSException {
        context.createProducer().send(queue, message);
    }

    private void doBeforeProcessing(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
        String userName = request.getParameter("userName");
        request.login(userName.trim(), request.getParameter("password"));
    }

    private void doAfterProcessing(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException, JMSException {

        if (request.isUserInRole("ROLE_ADMIN")) {
            sendMessageToDestination("Message");
            // Redirect to a secure area.
        } else if (request.isUserInRole("ROLE_USER")) {
            sendMessageToDestination("Message");
            // Redirect to a secure area.
        }

        //...
    }

    //...
}

я использую самозаверяющий сертификат SSL для чистой цели тестирования. Таким образом, он использует https://localhost:8443/ContextPath для доступа к защищенным веб-ресурсам

<transport-guarantee>CONFIDENTIAL</transport-guarantee> in web.xml.


обновление :

сообщение, управляемое Бобом, потребляющим сообщения:

@JMSDestinationDefinition(name = "destination", interfaceName = "javax.jms.Queue", resourceAdapter = "jmsra", destinationName = "destination")
@MessageDriven(activationConfig = {
    @ActivationConfigProperty(propertyName = "destinationLookup", propertyValue = "jms/destination"),
    @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
    @ActivationConfigProperty(propertyName = "connectionFactoryLookup", propertyValue = "java:jboss/exported/jms/destinationFactory"),
    @ActivationConfigProperty(propertyName = "messagingType", propertyValue = "javax.jms.MessageListener"),
    @ActivationConfigProperty(propertyName = "destination", propertyValue = "java:/jms/destination"),
    @ActivationConfigProperty(propertyName = "useJNDI", propertyValue = "true")
})
public class UserStatusMessageBean implements MessageListener {

    public UserStatusMessageBean() {}

    @Resource
    private MessageDrivenContext messageDrivenContext;
    @EJB
    private UserStatusService userStatusService;

    @Override
    public void onMessage(Message message) {

        try {
            if (message instanceof TextMessage) {
                TextMessage textMessage = (TextMessage) message;
                String text = textMessage.getText();

                if (StringUtils.isNotBlank(text)) {
                    userStatusService.addHost(text);
                } else {
                    System.out.println("No message found.");
                }
            } else {
                System.out.println("Message is of wrong type : " + message.getClass().getName());
            }
        } catch (JMSException e) {
            messageDrivenContext.setRollbackOnly();
            System.out.println(e);
        } catch (Throwable e) {
            System.out.println(e);
        }
    }
}

в вышеуказанный MDB вводится удаленный EJB, который требует определенных полномочий.

@Stateless
@DeclareRoles(value = {"ROLE_ADMIN", "ROLE_USER"})
@RolesAllowed(value = {"ROLE_ADMIN", "ROLE_USER"})
public class UserStatusBean implements UserStatusService {

    @PersistenceContext
    private EntityManager entityManager;

    @Override
    public void addHost(String hostName) {
        // Insert or update via JPA.
    }
}

когда приложение развернуто, сервер продолжает бросать следующее исключение рекурсивно, если false значение задается в,

<security-enabled>false</security-enabled>
20:21:55,343 ERROR [org.hornetq.ra] (default-threads - 3) HQ154003: Unable to reconnect org.hornetq.ra.inflow.HornetQActivationSpec(ra=org.hornetq.ra.HornetQResourceAdapter@dc9e56 destination=java:/jms/destination destinationType=javax.jms.Queue ack=Auto-acknowledge durable=false clientID=null user=null maxSession=15): HornetQSecurityException[errorType=SECURITY_EXCEPTION message=HQ119032: User: null doesnt have permission=CONSUME on address {2}]
    at org.hornetq.core.protocol.core.impl.ChannelImpl.sendBlocking(ChannelImpl.java:399)
    at org.hornetq.core.client.impl.ClientSessionImpl.internalCreateConsumer(ClientSessionImpl.java:2064)
    at org.hornetq.core.client.impl.ClientSessionImpl.createConsumer(ClientSessionImpl.java:527)
    at org.hornetq.core.client.impl.ClientSessionImpl.createConsumer(ClientSessionImpl.java:474)
    at org.hornetq.core.client.impl.DelegatingSession.createConsumer(DelegatingSession.java:206)
    at org.hornetq.ra.inflow.HornetQMessageHandler.setup(HornetQMessageHandler.java:184)
    at org.hornetq.ra.inflow.HornetQActivation.setup(HornetQActivation.java:340)
    at org.hornetq.ra.inflow.HornetQActivation.handleFailure(HornetQActivation.java:768)
    at org.hornetq.ra.inflow.HornetQActivation$SetupActivation.run(HornetQActivation.java:823)
    at org.jboss.jca.core.workmanager.WorkWrapper.run(WorkWrapper.java:226)
    at org.jboss.threads.SimpleDirectExecutor.execute(SimpleDirectExecutor.java:33)
    at org.jboss.threads.QueueExecutor.runTask(QueueExecutor.java:808)
    at org.jboss.threads.QueueExecutor.access0(QueueExecutor.java:45)
    at org.jboss.threads.QueueExecutor$Worker.run(QueueExecutor.java:828)
    at java.lang.Thread.run(Thread.java:745)
    at org.jboss.threads.JBossThread.run(JBossThread.java:320)

1 ответов


я воспроизвел ту же проблему на WildFly 9.0.2, (используя ресурс REST EJB вместо вашего сервлета)

23:31:22,138 ERROR [io.undertow.request] (default task-7) UT005023: Exception handling request to /jeeshop-admin/rs/users/administrators: org.jboss.resteasy.spi.UnhandledException: javax.jms.JMSSecurityException: HQ119032: User: null doesnt have permission=SEND on address {2}
    at org.jboss.resteasy.core.ExceptionHandler.handleApplicationException(ExceptionHandler.java:76)

чтобы исправить это, я сделал следующее:

@Resource(mappedName = "java:jboss/exported/jms/destinationFactory")
ConnectionFactory factory;

private void sendMessageToDestination(String message, String user) throws JMSException {
    try (Connection connection = factory.createConnection(user,"hardcodedPassword");
         Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
         MessageProducer producer = session.createProducer(queue)) {

        TextMessage textMessage = session.createTextMessage(message);

        producer.send(textMessage);
    }
}

так как вы можете видеть, что я предоставляю действительное имя пользователя и пароль во время создания соединения. Этот пользователь имеет ту же роль, что и пользователь, настроенный в настройках безопасности hornetq-server.

Я не использовал точно такой же домен безопасности, как вы тогда (я использовал мой собственный код, чтобы воспроизвести проблему). В случай ваш не работает хорошо, вот он:

<security-domain name="jeeshop" cache-type="default">
    <authentication>
        <login-module code="Database" flag="required">
            <module-option name="dsJndiName" value="java:/JeeshopDS"/>
            <module-option name="principalsQuery" value="select password from User where login = ? and (disabled is null or disabled = 0) and activated = 1"/>
            <module-option name="rolesQuery" value="select name,'Roles' from Role r, User_Role ur, User u where u.login=? and u.id = ur.userId and r.id = ur.roleId"/>
            <module-option name="hashAlgorithm" value="SHA-256"/>
            <module-option name="hashEncoding" value="base64"/>
            <module-option name="unauthenticatedIdentity" value="guest"/>
        </login-module>
    </authentication>
</security-domain>

мой источник данных:

<xa-datasource jndi-name="java:/JeeshopDS" pool-name="JeeshopDS" enabled="true">
    <xa-datasource-property name="ServerName">
        localhost
    </xa-datasource-property>
    <xa-datasource-property name="DatabaseName">
        jeeshop
    </xa-datasource-property>
    <driver>mysql</driver>
    <security>
        <user-name>jeeshop</user-name>
        <password>test</password>
    </security>
    <validation>
        <valid-connection-checker class-name="org.jboss.jca.adapters.jdbc.extensions.mysql.MySQLValidConnectionChecker"/>
        <exception-sorter class-name="org.jboss.jca.adapters.jdbc.extensions.mysql.MySQLExceptionSorter"/>
    </validation>
</xa-datasource>

извлечение моего DDL для хранения ролей:

CREATE TABLE IF NOT EXISTS Role (
  id bigint(20) NOT NULL AUTO_INCREMENT,
  name varchar(255) NOT NULL,
  PRIMARY KEY (id),
  UNIQUE KEY UK_Role_name (name)
);

CREATE TABLE IF NOT EXISTS User_Role (
  userId bigint(20) NOT NULL,
  roleId bigint(20) NOT NULL,
  PRIMARY KEY (userId,roleId)
);

редактировать

следующий MDB позволяет читать пункт назначения, где sendMessageToDestination() производит сообщения:

@MessageDriven(activationConfig = {
        @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
        @ActivationConfigProperty(propertyName = "useJNDI", propertyValue = "true"),
        @ActivationConfigProperty(propertyName = "destination", propertyValue = "java:jboss/exported/jms/destination"),
        @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge")})
public class TestMDB implements MessageListener {

    @Override
    @PermitAll
    public void onMessage(Message message) {

        if (message instanceof TextMessage) {
            try {
                System.out.println(((TextMessage) message).getText());
            } catch (JMSException e) {
                // propagate for transaction rollback
                throw new IllegalArgumentException(e);
            }
        }

    }
}

вы можете в конечном итоге изменить Принципал, используемый MDB. Видеть это ссылки: