【问题标题】:Connect to EMS JMS queue using Spring + SSL使用 Spring + SSL 连接到 EMS JMS 队列
【发布时间】:2013-05-12 08:41:27
【问题描述】:

我在使用 SSL 和带有证书的相互身份验证创建与 Tibco EMS JMS 队列的连接(和读取)时遇到了一些问题。 这是我的 Spring 配置:

<!-- TIBCO Connection Factory Bean -->
<bean id="tibcoConnectionFactory" class="com.tibco.tibjms.TibjmsConnectionFactory">
  <constructor-arg value="ssl://mytibco.server.address:30113" />
  <property name="userName" value="userName" />
  <property name="userPassword" value="${tibcoPwd}" />
  <property name="connAttemptCount" value="10" />
  <property name="connAttemptDelay" value="100" />
  <property name="connAttemptTimeout" value="1000" />
  <property name="reconnAttemptCount" value="10" />
  <property name="reconnAttemptDelay" value="100" />
  <property name="reconnAttemptTimeout" value="1000" />
  <property name="SSLVendor" value="j2se" />
  <property name="SSLEnableVerifyHost" value="false" />
  <property name="SSLEnableVerifyHostName" value="false" />
  <property name="SSLTrace" value="true" />
  <property name="SSLDebugTrace" value="true" />
  <property name="SSLIdentity" value="c:\\cert\\testCert.p12" />
  <property name="SSLPassword" value="*******" />
</bean>

<!-- Spring CachingConnectionFactory Bean -->
<bean id="tibcoJmsConnectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
  <constructor-arg ref="tibcoConnectionFactory" />
  <property name="reconnectOnException" value="true" />
  <property name="sessionCacheSize" value="10" />
</bean>

当我尝试将某些内容放入队列时,我收到以下堆栈跟踪:

[TIBCO EMS]: [J] [SSL] initializing security with vendor 'j2se'
[TIBCO EMS]: [J] [SSL] client version 5.1.0, security version 3.0.0, SSL initialized with vendor 'j2se'
[TIBCO EMS]: [J] [SSL] WARNING: server verification is disabled, will trust any server.
[TIBCO EMS]: [J] [SSL] reading client identity from byte array, format=AUTO
WARN  [jmsContainer-1] org.springframework.jms.listener.DefaultMessageListenerContainer - Execution of JMS message listener failed
org.springframework.jms.JmsSecurityException: Error occured while reading identity data: Invalid or not supported identity data; nested exception is javax.jms.JMSSecurityException: Error occured while reading identity data: Invalid or not supported identity data
   at org.springframework.jms.support.JmsUtils.convertJmsAccessException(JmsUtils.java:283)
   at org.springframework.jms.support.JmsAccessor.convertJmsAccessException(JmsAccessor.java:168)
   at org.springframework.jms.core.JmsTemplate.execute(JmsTemplate.java:474)
   at org.springframework.jms.core.JmsTemplate.execute(JmsTemplate.java:436)
   ...
   at org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:543)
   at org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:482)
   at org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:451)
   at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecute(AbstractPollingMessageListenerContainer.java:323)
   at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:241)
   at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:982)
   at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.executeOngoingLoop(DefaultMessageListenerContainer.java:974)
   at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:876)
   at java.lang.Thread.run(Thread.java:662)
Caused by: javax.jms.JMSSecurityException: Error occured while reading identity data: Invalid or not supported identity data
   at com.tibco.tibjms.TibjmsSSL._identityFromStore(TibjmsSSL.java:2670)
   at com.tibco.tibjms.TibjmsSSL.createIdentity(TibjmsSSL.java:2575)
   at com.tibco.tibjms.TibjmsxLinkSSL._initSSL(TibjmsxLinkSSL.java:309)
   at com.tibco.tibjms.TibjmsxLinkSSL.connect(TibjmsxLinkSSL.java:390)
   at com.tibco.tibjms.TibjmsConnection._create(TibjmsConnection.java:1288)
   at com.tibco.tibjms.TibjmsConnection.<init>(TibjmsConnection.java:4115)
   at com.tibco.tibjms.TibjmsxCFImpl._createImpl(TibjmsxCFImpl.java:209)
   at com.tibco.tibjms.TibjmsxCFImpl._createConnection(TibjmsxCFImpl.java:253)
   at com.tibco.tibjms.TibjmsConnectionFactory.createConnection(TibjmsConnectionFactory.java:36)
   at org.springframework.jms.connection.SingleConnectionFactory.doCreateConnection(SingleConnectionFactory.java:343)
   at org.springframework.jms.connection.SingleConnectionFactory.initConnection(SingleConnectionFactory.java:290)
   at org.springframework.jms.connection.SingleConnectionFactory.createConnection(SingleConnectionFactory.java:227)
   at org.springframework.jms.support.JmsAccessor.createConnection(JmsAccessor.java:184)
   at org.springframework.jms.core.JmsTemplate.access$500(JmsTemplate.java:90)
   at org.springframework.jms.core.JmsTemplate$JmsTemplateResourceFactory.createConnection(JmsTemplate.java:1028)
   at org.springframework.jms.connection.ConnectionFactoryUtils.doGetTransactionalSession(ConnectionFactoryUtils.java:298)
   at org.springframework.jms.core.JmsTemplate.execute(JmsTemplate.java:458)
   ... 12 more

到目前为止,我无法成功解决 ssl 握手问题。 如何解决这个问题?

【问题讨论】:

    标签: spring ssl certificate ems


    【解决方案1】:

    您遇到的问题是由于 Spring 和 com.tibco.tibjms.TibjmsConnectionFactory 重载 setSSLIdentity 方法这一事实的结合,从而允许传递 byte[]String

    这让 Spring 感到困惑,它正在调用 setSSLIdentity(byte[]),这意味着 com.tibco.tibjms.TibjmsConnectionFactory 将字符串 c:\\cert\\testCert.p12 的字节视为证书(显然不是)。

    不幸的是,Spring 不允许您在 property 元素上强制类型(就像它在 constructor-arg 上所做的那样,至少在撰写本文时是这样),因此您将使用采用 java.utils.Map 的构造函数并将配置作为属性传递:

    <bean id="tibcoConnectionFactory" class="com.tibco.tibjms.TibjmsConnectionFactory">
      <constructor-arg value="ssl://mytibco.server.address:30113" />
      <constructor-arg><null/></constructor-arg>
      <constructor-arg>
        <util:map>
          <entry key="com.tibco.tibjms.factory.username" value="userName"/>
          <entry key="com.tibco.tibjms.factory.password" value="${tibcoPwd}"/>
          <entry key="com.tibco.tibjms.connect.attemptcount" value="10"/>
          <entry key="com.tibco.tibjms.connect.attemptdelay" value="100"/>
          <entry key="com.tibco.tibjms.connect.attempttimeout" value="1000"/>  
          <entry key="com.tibco.tibjms.reconnect.attemptcount" value="10"/>
          <entry key="com.tibco.tibjms.reconnect.attemptdelay" value="10-"/>
          <entry key="com.tibco.tibjms.reconnect.attempttimeout" value="1000" />  
          <entry key="com.tibco.tibjms.ssl.vendor" value="j2se"/>
          <entry key="com.tibco.tibjms.ssl.enable_verify_host" value="false"/>
          <entry key="com.tibco.tibjms.ssl.enable_verify_hostname" value="false"/>
          <entry key="com.tibco.tibjms.ssl.trace" value="true"/>
          <entry key="com.tibco.tibjms.ssl.debug_trace" value="true"/>
          <entry key="com.tibco.tibjms.ssl.identity" value="c:/cert/testCert.p12"/>
          <entry key="com.tibco.tibjms.ssl.password" value="value="*******"/>  
        <util:map>
      </constructor-arg>
    </bean>
    

    对于任何寻找其他属性名称的人,您可以深入了解相关的 setter 并在那里查看属性名称。

    【讨论】:

      【解决方案2】:

      它似乎没有正确读取 .p12。它必须记录如下内容:

      [TIBCO EMS]:[J] [SSL] 从文件 'c:\cert\testCert.p12' 中读取客户端身份,格式=PKCS12

      注意格式=...

      【讨论】:

        【解决方案3】:

        SSLIdentity 输入为/c:/cert/testCert.p12。然后只有它会识别您的 p12 文件,否则会将其视为字节数组

        【讨论】:

          【解决方案4】:

          问题在于 TibjmsConnectionFactory 重载了 setSSLIdentity(..) 设置器。

          可用的设置器是:

          setSSLIdentity(byte[] identity)

          setSSLIdentity(java.lang.String sslIdentity)

          这意味着 Spring 不知道要调用哪个 setter。我还没有研究过这一点的证据,但是从谷歌搜索中我发现由 JVM 实现来决定将调用哪个设置器,并且在我的情况下,每次应用程序重新启动(Oracle JVM)都不同。事实上,这是一个已知问题,请参阅https://github.com/flyway/flyway/issues/890

          一种解决方案是使用包含您的属性的Map 调用构造函数:

          TibjmsConnectionFactory(java.lang.String serverUrl, java.lang.String clientId, java.util.Map properties)

          另见https://docs.tibco.com/pub/enterprise_message_service/8.1.0/doc/html/tib_ems_api_reference/api/javadoc/com/tibco/tibjms/TibjmsConnectionFactory.html#setSSLIdentity(java.lang.String)

          PS:很抱歉复活了一个老问题,但由于这个问题的访问量很高,这可能会在未来帮助其他人。

          【讨论】:

            猜你喜欢
            • 2011-10-09
            • 1970-01-01
            • 2020-09-13
            • 2019-05-19
            • 2017-02-14
            • 1970-01-01
            • 1970-01-01
            • 2019-10-23
            • 2014-08-31
            相关资源
            最近更新 更多