简体   繁体   English

尝试订阅 ActiveMQ Artemis ManagementNotifications 时出现 JMSSecurity 异常

[英]JMSSecurity exception while trying to subscribe to ActiveMQ Artemis ManagementNotifications

I'm using Spring Boot to perform a JNDI lookup so I can subscribe to Artemis' management notifications and figure out when a client is no longer subscribed to a particular topic.我正在使用 Spring Boot 来执行JNDI lookup ,因此我可以订阅 Artemis 的管理通知并确定客户端何时不再订阅特定主题。 I'm fairly new to JNDI and my understanding is that the code snippet I've provided causes a connection to an existing Artemis broker to be established and consequently captures notifications being sent by the broker.我对 JNDI 还很陌生,我的理解是,我提供的代码片段会导致建立与现有 Artemis 代理的连接,从而捕获代理发送的通知。

I get an error when control hits the connection = cf.createConnection();当控制点击connection = cf.createConnection(); line in the code snippet provided.提供的代码片段中的行。

Error:错误:

Caused by: javax.jms.JMSSecurityException: AMQ229031: Unable to validate user from /ip:port. Username: null; SSL certificate subject DN: unavailable
...
Caused by: org.apache.activemq.artemis.api.core.ActiveMQSecurityException: AMQ229031: Unable to validate user from /ip:port. Username: null; SSL certificate subject DN: unavailable

How do I include the username, password, keystore and truststore in the InitialContext so that this error doesn't show up?如何在InitialContext中包含用户名、密码、密钥库和信任库,以便不显示此错误?

Code I'm using:我正在使用的代码:

@ComponentScan({"com.management.notifications"})
@SpringBootApplication
public class ManagementNotificationTestApplication {

    @Value("${JMS_BROKER_TRUSTSTORE}")
    private String pathToTrustStore;

    public static void main(String[] args) {
        SpringApplication.run(ManagementNotificationTestApplication.class);
    }


    @EventListener(ApplicationReadyEvent.class)
    public void doSomething() throws NamingException, JMSException {
        Connection connection = null;
        InitialContext initialContext = null;
        try {
            Properties properties = new Properties();
            properties.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.apache.activemq.artemis.jndi.ActiveMQInitialContextFactory");
            properties.setProperty(Context.PROVIDER_URL, "tcp://ipAddress:portNumber?&" + "sslEnabled=true&" +
                    "trustStorePath=" + pathToTrustStore + "&trustStorePassword=" + "abc");

            // Step 1. Create an initial context to perform the JNDI lookup.
            initialContext = new InitialContext(properties);

            // Step 3. Perform a lookup on the Connection Factory
            ConnectionFactory cf = (ConnectionFactory) initialContext.lookup("ConnectionFactory");

            // Step 4.Create a JMS connection, a session and a producer for the queue
            connection = cf.createConnection();
            Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

            // Step 5. Perform a lookup on the notifications topic
            Topic notificationsTopic = (Topic) initialContext.lookup("topic/notificationsTopic");

            // Step 6. Create a JMS message consumer for the notification queue and set its message listener
            // It will display all the properties of the JMS Message
            MessageConsumer notificationConsumer = session.createConsumer(notificationsTopic);
            notificationConsumer.setMessageListener(new MessageListener() {
                @Override
                public void onMessage(final Message notif) {
                    System.out.println("------------------------");
                    System.out.println("Received notification:");
                    try {
                        Enumeration propertyNames = notif.getPropertyNames();
                        while (propertyNames.hasMoreElements()) {
                            String propertyName = (String) propertyNames.nextElement();
                            System.out.format("  %s: %s%n", propertyName, notif.getObjectProperty(propertyName));
                        }
                    } catch (JMSException e) {
                    }
                    System.out.println("------------------------");
                }
            });

            // Step 7. Start the Connection to allow the consumers to receive messages
            connection.start();

            // Step 10. Try to create a connection with unknown user
            try {
                cf.createConnection("not.a.valid.user", "not.a.valid.password");
            } catch (JMSException e) {
            }

            // sleep a little bit to be sure to receive the notification for the security
            // authentication violation before leaving the example
            /*Thread.sleep(2000);*/
        } finally {
            // Step 11. Be sure to close the resources!
            if (initialContext != null) {
                initialContext.close();
            }
            if (connection != null) {
                connection.close();
            }
        }
    }
}

There's nothing wrong with your JNDI code.您的 JNDI 代码没有任何问题。 You just need to pass the username and password via createConnection(String, String) .您只需要通过createConnection(String, String)传递用户名和密码。 This is standard practice in JMS.这是 JMS 中的标准做法。

It's worth noting that the fact that you're getting an authentication error means that your SSL configuration is working.值得注意的是,您收到身份验证错误意味着您的 SSL 配置正在运行。 If your SSL config wasn't correct then you'd get an SSL error before you even made a successful connection to the broker and tried to authenticate.如果您的 SSL 配置不正确,那么在您成功连接到代理并尝试进行身份验证之前,您会收到 SSL 错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM