【发布时间】:2017-07-25 10:18:57
【问题描述】:
我目前正在处理一个 JMS 项目,我已经创建了 2 个密钥和 2 个证书以及一个 TrustStorage,我通过 Qpid 的 UI 创建了 mytruststore。 在我的 jndi.properties 文件中,我有以下代码:
//Set the InitialContextFactory class to use
java.naming.factory.initial = org.apache.qpid.jms.jndi.JmsInitialContextFactory
//Define the required ConnectionFactory instances
//connectionfactory.<JNDI-lookup-name> = <URI>
connectionfactory.myFactoryLookup = amqp://localhost:5672
connectionfactory.producerConnectionFactory = amqp://admin:admin@?brokerlist='tcp://localhost:5672?encryption_remote_trust_store='$certificates%255c/mytruststore''
connectionfactory.consumer1ConnectionFactory = amqp://admin:admin@?brokerlist='tcp://localhost:5672?encryption_key_store='C:\OpenSSL-Win64\bin\mytruststorage.jks'&encryption_key_store_password='thanos''
connectionfactory.consumer2ConnectionFactory = amqp://admin:admin@?brokerlist='tcp://localhost:5672?encryption_key_store='C:\OpenSSL-Win64\bin\mytruststorage.jks'&encryption_key_store_password='thanos''
//Configure the necessary Queue and Topic objects
//queue.<JNDI-lookup-name> = <queue-name>
//topic.<JNDI-lookup-name> = <topic-name>
queue.myQueueLookup = queue
topic.myTopicLookup = topic
queue.myTestQueue = queue
在我的 EncryptionExample.java 类中,我有以下代码:
package org.apache.qpid.jms.example;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import javax.jms.BytesMessage;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.DeliveryMode;
import javax.jms.Destination;
import javax.jms.ExceptionListener;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
public class EncryptionExample {
public EncryptionExample() {
}
public static void main(String[] args) throws Exception {
EncryptionExample encryptionExampleApp = new EncryptionExample();
encryptionExampleApp.runProducerExample();
encryptionExampleApp.runReceiverExample();
}
private void runProducerExample() throws Exception
{
Connection connection = createConnection("producerConnectionFactory");
try {
Session session = connection.createSession(true, Session.SESSION_TRANSACTED);
Destination destination = createDesination("myTestQueue");
MessageProducer messageProducer = session.createProducer(destination);
TextMessage message = session.createTextMessage("Hello world!");
// ============== Enable encryption for this message ==============
message.setBooleanProperty("x-qpid-encrypt", true);
// ============== Configure recipients for encryption ==============
message.setStringProperty("x-qpid-encrypt-recipients", "CN=client1, OU=Qpid, O=Apache, C=US");
messageProducer.send(message);
session.commit();
}
finally {
connection.close();
}
}
private void runReceiverExample() throws Exception
{
Connection connection = createConnection("consumer1ConnectionFactory");
try {
connection.start();
Session session = connection.createSession(true, Session.SESSION_TRANSACTED);
Destination destination = createDesination("myTestQueue");
MessageConsumer messageConsumer = session.createConsumer(destination);
Message message = messageConsumer.receive();
if (message instanceof TextMessage) {
// application logic
System.out.println(((TextMessage) message).getText());
} else if (message instanceof BytesMessage) {
// handle potential decryption failure
System.out.println("Potential decryption problem. Application not in list of intended recipients?");
}
session.commit();
}
finally {
connection.close();
}
}
///////////////////////////////////////
// The following is boilerplate code //
///////////////////////////////////////
private Connection createConnection(final String connectionFactoryName) throws JMSException, IOException, NamingException
{
try (InputStream resourceAsStream = getResourceAsStream("jndi.properties")) {
Properties properties = new Properties();
properties.load(resourceAsStream);
Context context = new InitialContext(properties);
ConnectionFactory connectionFactory = (ConnectionFactory) context.lookup(connectionFactoryName);
final Connection connection = connectionFactory.createConnection();
context.close();
return connection;
}
}
private InputStream getResourceAsStream(String string) {
// TODO Auto-generated method stub
return null;
}
private Destination createDesination(String desinationJndiName) throws IOException, NamingException
{
try (InputStream resourceAsStream = this.getClass().getResourceAsStream("example.properties")) {
Properties properties = new Properties();
properties.load(resourceAsStream);
Context context = new InitialContext(properties);
Destination destination = (Destination) context.lookup(desinationJndiName);
context.close();
return destination;
}
}
}
当我尝试构建它时,出现以下异常。
线程“主”java.lang.NullPointerException 中的异常
在 java.util.Properties$LineReader.readLine(Unknown Source)
在 java.util.Properties.load0(未知来源)
在 java.util.Properties.load(Unknown Source)
在 org.apache.qpid.jms.example.EncryptionExample.createConnection(EncryptionExample.java:106)
在 org.apache.qpid.jms.example.EncryptionExample.runProducerExample(EncryptionExample.java:54)
在 org.apache.qpid.jms.example.EncryptionExample.main(EncryptionExample.java:48)
我认为 jndi.properties 文件中的以下代码有问题:
connectionfactory.myFactoryLookup = amqp://localhost:5672
connectionfactory.producerConnectionFactory = amqp://admin:admin@?brokerlist='tcp://localhost:5672?encryption_remote_trust_store='$certificates%255c/mytruststore''
connectionfactory.consumer1ConnectionFactory = amqp://admin:admin@?brokerlist='tcp://localhost:5672?encryption_key_store='C:\OpenSSL-Win64\bin\mytruststorage.jks'&encryption_key_store_password='thanos''
connectionfactory.consumer2ConnectionFactory = amqp://admin:admin@?brokerlist='tcp://localhost:5672?encryption_key_store='C:\OpenSSL-Win64\bin\mytruststorage.jks'&encryption_key_store_password='thanos''
这是我的解决方案资源管理器:
【问题讨论】:
-
jndi.properties在哪里? -
我已通过添加解决方案资源管理器的图片来编辑帖子。
-
NullPointerException 来自您自己的代码。您有一个方法 getResourceAsStream 未实现并返回 null。你可能是想打电话给docs.oracle.com/javase/8/docs/api/java/lang/…
-
我还注意到您正在尝试将 Qpid JMS 客户端 (qpid.apache.org/components/jms/index.html) 与消息加密功能一起使用。这行不通。我们尚未决定如何在 AMQP 1.0 中表示加密消息,并且 Qpid JMS 客户端(使用 AMQP 1.0)不提供支持。用于 AMQP 0-8..0-10 (qpid.apache.org/components/jms/amqp-0-x.html) 的旧 Qpid JMS 确实以 Qpid 供应商特定的方式支持该功能。如果您使用 Maven,如果您想使用此功能,则需要从使用 artefact qpid-jms-client 切换到 quid-client。