Настройка доверенных пакетов (ActiveMQ) - PullRequest
0 голосов
/ 19 марта 2020

Я пытаюсь отправлять получать сообщения ActiveMQ. Но я вижу, что сообщения возвращаются с этим сообщением.

JMSException in onMessage(): javax.jms.JMSException: Failed to build body from content. Serializable class not available to broker. Reason: java.lang.ClassNotFoundException: Forbidden class com.logicalprovisioning.common.gtc.shared.GTCMessage! This class is not trusted to be serialized as ObjectMessage payload. Please take a look at http://activemq.apache.org/objectmessage.html for more information on how to configure trusted classes.

Поэтому я прочитал ссылку в сообщении. И я пытался следовать инструкциям. Хотя я должен сказать, что не очень хорошо написано, куда поместить конфигурацию.

Итак, я сделал следующее: 1. Я отредактировал строку ACTIVEMQ_OPTS в файле activemq.bat в папке bin на

if "%ACTIVEMQ_OPTS%" == "" set ACTIVEMQ_OPTS=-Xms1G -Xmx1G -Djava.util.logging.config.file=logging.properties -Djava.security.auth.login.config="%ACTIVEMQ_CONF%\login.config" -Dorg.apache.activemq.SERIALIZABLE_PACKAGES=com.logicalprovisioning.common.gtc.shared.GTCMessage

Это не сработало.

Я также добавил вышеупомянутую строку в activemq.bat папки win64. Это не сработало.

Я изменил создание объекта подписчика для добавления доверенных пакетов. Например:

String providerEndpoints = "tcp://" + host + ":" + port + "?wireFormat.maxInactivityDuration=7200000";

// Set the trusted packages/classes to move back and forth on the ActiveMQ JMS service.
ArrayList<String> trustedClasses = new ArrayList<String>();

trustedClasses.add("com.logicalprovisioning.common.gtc.shared.GTCMessage");

// Obtain the factory
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory();

activeMQConnectionFactory.setBrokerURL(providerEndpoints);

// Add the trusted packages/classes to the ActiveMQ consumer.
activeMQConnectionFactory.setTrustedPackages(trustedClasses);

//Create the connection
setConnection(activeMQConnectionFactory.createQueueConnection());
getConnection().setClientID(this.getName());

// Make a session
setSession(getConnection().createQueueSession(false, Session.AUTO_ACKNOWLEDGE));

getSession().createQueue(jmsDestination);

// Create the destination
Destination destination = getSession().createQueue(jmsDestination);

String selector = "JMSCorrelationID = '" + getActionRequest().getOriginId() + "_" + getActionRequest().getRequestId() + "'" ;

setConsumer(getSession().createConsumer(destination, selector));
getConsumer().setMessageListener(new DefaultMessageListener(this));

// Start ...
gtcMessages = new GTCMessageQueue<GTCMessage>();  // We'll need a message store now
getConnection().start();

И я добавил для своего продюсера что-то похожее, например:

    Context initialContext = new InitialContext();
        Context environmentContext = (Context) initialContext.lookup("java:comp/env");

        String queueConnectionFactoryNameLookup = PalInit.getProperty("jms.queue.connection.factory");

        // Set the trusted packages/classes to move back and forth on the ActiveMQ JMS service.
        ArrayList<String> trustedClasses = new ArrayList<String>();

        trustedClasses.add("com.logicalprovisioning.common.gtc.shared.GTCMessage");

        ActiveMQConnectionFactory activeMQConnectionFactory = (ActiveMQConnectionFactory) environmentContext.lookup(queueConnectionFactoryNameLookup);

        activeMQConnectionFactory.setTrustedPackages(trustedClasses);
        // Create connection
        QueueConnection queueConnection = activeMQConnectionFactory.createQueueConnection();
        queueConnection.start();

        // Create session and producer
        setSession(queueConnection.createSession(false, Session.AUTO_ACKNOWLEDGE));

        String queueName = PalInit.getProperty("jms.destination");
        Queue jmsQueue = getSession().createQueue(queueName);

        setProducer(getSession().createProducer(jmsQueue));
        setQueueConnection(queueConnection);

        // Set Message "Time to Live" to the request timeout plus 10 minutes
        getProducer().setTimeToLive(getTimeout() + (10 * 60 * 1000L));

Но, похоже, ничего не работает. У меня есть банка ActiveMQ-All в папке lib Tomcat, а также банка, где находится класс GTCMessage. Может кто-нибудь сказать, пожалуйста, что я делаю не так? Это проблема отсутствующего класса или моей плохой конфигурации? Любая помощь будет оценена. Спасибо!

Приложение работает на Tomcat 9, JAVA 1.8 и Active MQ 5.15.11.

1 Ответ

2 голосов
/ 19 марта 2020

Я думаю, ваша проблема в том, что вы задаете имя специфицированного c класса , а не пакета класса. Код просматривает имя пакета, а не имя класса. Попробуйте это:

// Set the trusted packages to move back and forth on the ActiveMQ JMS service.
ArrayList<String> trustedPackages = new ArrayList<String>();
trustedPackages.add("com.logicalprovisioning.common.gtc.shared");
ActiveMQConnectionFactory activeMQConnectionFactory = (ActiveMQConnectionFactory) environmentContext.lookup(queueConnectionFactoryNameLookup);
activeMQConnectionFactory.setTrustedPackages(trustedPackages);        

Я не думаю, что вам нужно будет установить это на самого брокера.

Кроме того, я бы настоятельно рекомендовал вам не использовать JMS ObjectMessage. Они зависят от сериализации Java, чтобы маршалировать и демаршировать полезную нагрузку своего объекта. Этот процесс обычно считается небезопасным, поскольку вредоносная полезная нагрузка может использовать хост-систему. Для этого было создано множество CVE , поэтому большинство провайдеров JMS вынуждают пользователей явным образом вносить в белый список пакеты, которыми можно обмениваться с помощью сообщений ObjectMessage.

Существует также ряд других проблем. с использованием JMS ObjectMessage, не связанной с безопасностью, которую вы должны прочитать о . В этой статье есть хорошее предложение о том, как заменить ObjectMessage - определить представление данных для полезной нагрузки (JSON, protobuf, XML) и использовать TextMessage или BytesMessage для его переноса.

...