使用 Qpid 通过 SSL 与 AMQP 1.0 代理通信
Posted
技术标签:
【中文标题】使用 Qpid 通过 SSL 与 AMQP 1.0 代理通信【英文标题】:Communicating with AMQP 1.0 broker over SSL using Qpid 【发布时间】:2013-10-10 11:03:26 【问题描述】:我正在使用 ActiveMQ 5.8.0,它支持 AMQP 1.0 作为队列代理。我正在尝试使用 Qpid AMQP1.0 客户端 jms 库从 Java 客户端与此通信,但没有看到指定密钥库和信任库信息的方法。
我已经通过 Java VM 选项(例如 -Djavax.net.ssl.keyStore)传入 SSL 凭据成功配置了客户端,但是对于我的最终解决方案,这不是可接受的方法...我需要能够从代码中指定此信息。
我目前正在使用 createFromURL 方法从包含定义为 here 的 SSL 参数的 URL 生成连接,但似乎没有从 URL 解析密钥库信息(以及可能的故障转移参数)。
String connectionUrl = "amqps://localhost/?brokerlist='tcp://localhost:5671?ssl='true'&key_store='C:/apache-activemq-5.8.0/conf/client.ks'&key_store_password='password'&trust_store='C:/apache-activemq-5.8.0/conf/client.ts'&trust_store_password='password'";
ConnectionFactoryImpl connectionFactory = ConnectionFactoryImpl.createFromURL(connectionUrl);
有谁知道将安全信息提供给连接的更好方法?
更新: 对,所以通过 API 进行一些挖掘,我发现该库使用默认 SSLSocketFactory
参见:org.apache.qpid.amqp_1_0.client.Connection
final Socket s;
if(ssl)
s = SSLSocketFactory.getDefault().createSocket(address, port);
因此,似乎无法在 JVM 选项之外指定此信息以设置默认值……至少在当前版本的 Qpid 客户端库中。
【问题讨论】:
【参考方案1】:QPID JMS AMQP 1.0 客户端的连接 URL 参数与之前 AMQP 版本的参数略有不同。
以下是适用于 1.0 客户端的连接 URL 示例:
amqp://myhost:myport?ssl=true&ssl-cert-alias=myalias&clientid=myclientid&remote-host=default&sync-publish=false&trust-store=C:/trusstore.ts&trust-store-password=mytrustkeypass&key-store=C:/keystore.ks&key-store-password=mykeypass
另见this link
【讨论】:
【参考方案2】:URL 是放置 SSL 参数的正确位置吗?
ConnectionFactory
不应该得到javax.net.ssl.SSLContext
然后创建连接吗?
(我不熟悉 ActiveMQ API 的细节。)
【讨论】:
感谢您的回复。我相信 ConnectionFactory 负责设置队列通信,因此我无法直接控制它如何检索 SSLContext。如前所述,如果我传入 JVM 选项来配置 SSLContext(即 -D javax.net.ssl.trustStore=...),那么工厂使用密钥库信息并且 SSL 握手工作正常。问题是我与不同的密钥库有多个 SSL 通信,所以我不能使用全局 JVM 选项。我需要一种为此特定连接传递 SSL 信息的方法——如果这有意义的话。 我对 RabbitMQ 比较熟悉,但认为 API 类似。他们的 ConnectionFactory 有一个方法 useSslProtocol(javax.net.ssl.SSLContext context)。 SSLContext 有一个 init 方法,我认为它采用您传递给 JVM 的参数。从那里我假设您可以为每个连接创建一个 SSLContext。 再次感谢,这似乎正是我想要的,但它似乎不存在。 ActiveMQ AMQP 页面 (activemq.apache.org/amqp.html) 指向似乎已失去此功能的 Java 客户端的 apache Qpid。 我明白了 - 用相关知识而不是特定知识来回复的危险 - 抱歉!在第一次扫描 Qpid 页面时,我没有看到 ConnectionFactory。 org.apache.activemq.ActiveMQSslConnectionFactory 在activemq中怎么样,或者你在客户端没有那个? 再次感谢。不错的尝试,但不幸的是,它不支持 AMQP 协议(我遇到了这个错误:***.com/questions/15788819/…)。这就是我使用 qpid 库的原因,并且我尝试在他们的邮件列表上发帖寻求具体帮助。不过,我感谢您的帮助。【参考方案3】:对于支持 AMQP 1.0.0 版的 0.9.0 版 QPid,client configuration page at QPID 也可以通过编程方式帮助完成此操作。
我还提供了一个成功程序的示例代码(注意:config 是我创建的一个类,用于存储我的所有配置值):
String ampqProtocol = "amqp";
List<String> queryVariables = new ArrayList<String>();
if(config.isUseSSL())
queryVariables.add("transport.keyStoreLocation="+config.getKeyStorePath());
queryVariables.add("transport.keyStorePassword="+config.getKeyStorePassword());
queryVariables.add("transport.trustStoreLocation="+config.getTrustStorePath());
queryVariables.add("transport.trustStorePassword="+config.getTrustStorePassword());
queryVariables.add("transport.keyAlias="+config.getKeyStoreAlias());
queryVariables.add("transport.contextProtocol="+config.getSslProtocol());
queryVariables.add("transport.verifyHost="+!config.isDontValidateSSLHostname());
ampqProtocol = "amqps";
String connectionString = ampqProtocol+"://"+config.getAddress()+":"+config.getPort();
if(!queryVariables.isEmpty())
try
connectionString += "?"+URLEncoder.encode(StringUtils.join(queryVariables, "&"), StandardCharsets.UTF_8.name());
catch (UnsupportedEncodingException e)
e.printStackTrace();
Hashtable<Object, Object> env = new Hashtable<Object, Object>();
env.put(Context.INITIAL_CONTEXT_FACTORY, "org.apache.qpid.jms.jndi.JmsInitialContextFactory");
env.put("connectionfactory.myFactoryLookup", connectionString);
Context context = null;
ConnectionFactory connectionFactory = null;
try
context = new InitialContext(env);
connectionFactory = (ConnectionFactory) context.lookup("myFactoryLookup");
catch (NamingException e)
e.printStackTrace();
Connection connection = null;
try
connection = connectionFactory.createConnection();
connection.start();
catch (JMSException e)
e.printStackTrace();
【讨论】:
以上是关于使用 Qpid 通过 SSL 与 AMQP 1.0 代理通信的主要内容,如果未能解决你的问题,请参考以下文章
从 Qpid JMS 客户端启用 AMQP 1.0 插件连接到 RabbitMQ 3.7.18 时出现错误匹配错误
解决Qpid与RabbitMQ端口冲突问题(epmd reports: node rabbit’ not running at all),RabbitMQ 3.11修改AMQP端口
AMQP Qpid Proton - 无法将消息发送到超过 256 个队列
使用 Spring、ActiveMQ 和 Qpid 进行集成测试