Qpid和JNDI用于加密消息

时间:2017-03-05 15:54:48

标签: java apache jms jndi qpid

我目前正在开发一个JMS项目,我创建了2个密钥和2个证书,以及我通过Qpid的UI创建的TrustStorage,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;
        }
    }
}

当我尝试构建它时,我会遇到以下例外情况。

  

线程中的异常&#34; main&#34;显示java.lang.NullPointerException

     

at java.util.Properties $ LineReader.readLine(Unknown Source)

     

at java.util.Properties.load0(Unknown Source)

     

at 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)

     

at 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''

这是我的解决方案资源管理器:

enter image description here

2 个答案:

答案 0 :(得分:1)

您遇到的第一个也是最大的问题是,您尝试使用客户端的连接URI和客户端功能,而不是您计划使用的客户端。您似乎正在使用Qpid JMS,这是在Qpid项目中开发的新AMQP 1.0客户端。此客户端使用与先前AMQP 0.x客户端不同的URI语法,并且在传入这些无效URI时,您将从连接工厂获得异常。

您将遇到的另一个问题(在您的帖子的评论中提到)是AMQP 1.0 JMS客户端中没有消息加密功能,因此一旦您正确定义了URI,这将是您的下一个问题。

较新的AMQP 1.0 JMS客户端的文档是here

答案 1 :(得分:0)

您无法在//文件中使用Properties进行评论。请改用#!

请参阅:https://docs.oracle.com/javase/8/docs/api/java/util/Properties.html#load-java.io.Reader-