我需要连接到我的应用程序中的远程队列,但是当在MQ场中启用安全性时它会遇到身份验证错误(RC 2035),我被告知当我使用spring配置时它试图访问一些默认队列不应该,我遇到setDirectAuth属性,它会解决这个问题吗?请告知我是否错过任何导致错误的属性?
错误:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'connectionFactory' defined in class path resource [META-INF/spring.xml]: Invocation of init method failed; nested exception is javax.naming.ServiceUnavailableException: Unable to connect to the target queue manager XXXX.XXX.XXX.com:1415/xxx.SVRCONN [Root exception is com.ibm.mq.MQException: MQJE001: Completion Code '2', Reason '2035'.]
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'connectionFactory' defined in class path resource [META-INF/spring.xml]: Invocation of init method failed; nested exception is javax.naming.ServiceUnavailableException: Unable to connect to the target queue manager xxxx.xxx.xxx.com:1415/xxx.SVRCONN [Root exception is com.ibm.mq.MQException: MQJE001: Completion Code '2', Reason '2035'.]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1455)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:567)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:913)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:464)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
context.xml中
<Resource
name="jms/MQConnectionFactory"
auth="Container"
type="com.ibm.mq.jms.MQQueueConnectionFactory"
factory="com.ibm.mq.jms.MQQueueConnectionFactoryFactory"
description="JMS Queue Connection Factory for sending messages"
HOST="XX.XXX.XXX.XX"
PORT="XXXX"
CHAN="MQ.CHANNEL"
TRAN="1"
QMGR="TEST01"
/>
<Resource
name="jms/QueueSU"
auth="Container"
type="com.ibm.mq.jms.MQQueue"
factory="com.ibm.mq.jms.MQQueueFactory"
description="JMS Queue for status update"
QU="Q01"
/>
<Resource
name="jms/QueueBM"
auth="Container"
type="com.ibm.mq.jms.MQQueue"
factory="com.ibm.mq.jms.MQQueueFactory"
description="JMS Queue for bond management"
QU="Q02"
/>
属性文件:
#JMS Provider
jms.factory.initial=com.ibm.mq.jms.context.WMQInitialContextFactory
jms.provider.url=xx.xxx.xxx.com:1415/xxx.CHANNEL
destination.factory=java:/comp/env/jms/MQConnectionFactory
bm.queue=java:/comp/env/jms/QueueBM
su.queue=java:/comp/env/jms/QueueSU
Spring.xml
<!-- JMS BEANS -->
<bean id="bmMessageReceiver" class="com.jms.BMMessageReceiver"/>
<bean id="suMessageReceiver" class="com.jms.SUMessageReceiver"/>
<bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
<property name="environment">
<props>
<prop key="java.naming.factory.initial">${jms.factory.initial}</prop>
<prop key="java.naming.provider.url">${jms.provider.url}</prop>
</props>
</property>
</bean>
<bean id="connectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate">
<ref bean="jndiTemplate" />
</property>
<property name="jndiName">
<value>${destination.factory}</value>
</property>
</bean>
<bean id="bmMessageQueue" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate">
<ref bean="jndiTemplate" />
</property>
<property name="jndiName">
<value>${bm.queue}</value>
</property>
</bean>
<bean id="suMessageQueue" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate">
<ref bean="jndiTemplate" />
</property>
<property name="jndiName">
<value>${su.queue}</value>
</property>
</bean>
<bean id="bmListenerContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="concurrentConsumers" value="5" />
<property name="connectionFactory" ref="connectionFactory" />
<property name="destination" ref="bmMessageQueue" />
<property name="messageListener" ref="bmMessageReceiver" />
<property name="sessionTransacted" value="true" />
</bean>
<bean id="suListenerContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="concurrentConsumers" value="5" />
<property name="connectionFactory" ref="connectionFactory" />
<property name="destination" ref="suMessageQueue" />
<property name="messageListener" ref="suMessageReceiver" />
<property name="sessionTransacted" value="true" />
</bean>
<!-- JMS END -->
答案 0 :(得分:1)
当您的应用打开本地队列时,授权配置文件会与打开的队列名称相匹配。换句话说,如果连接到LOCALQMGR
的应用打开SYSTEM.DEF.LOCAL.QUEUE@LOCALQMGR
,LOCALQMGR
上的授权控制列表条目必须授予应用SYSTEM.DEF.LOCAL.QUEUE
的访问权限。
但是,当应用程序打开SOME.QUEUE@REMOTEQMGR
时,QMgr会解析REMOTEQMGR
并找到导致该QMgr的传输队列。在这种情况下它打开的队列是传输队列,因此它查找与传输队列匹配的授权配置文件。将应用程序授权给XMitQ可以没问题,但它允许应用程序将消息发送到该QMgr上的任何队列,包括例如命令队列。
很多时候,管理员不希望直接授予对传输队列的访问权限,因为它允许访问该QMgr上的任何队列,而他们宁愿限制它。因此,在点对点界面中,通常在本地设置QRemote并将应用程序授权给它。在群集中,通常在群集队列上设置本地QAlias并将授权配置文件附加到该群集。
唯一会影响这一点的是应用用于连接请求的用户ID。如果QMgr是安全的,则应用程序无法做任何事情来影响此连接ID。 MQ管理员将在通道定义中设置ID,或者从IP地址或SSL证书可分辨名称映射它。如果由于某种原因QMgr不安全,应用程序可以指定在连接上使用的ID作为API调用的一部分:
connection = ConnectionFactory.createConnection(userID, password);
如果MQ管理员未在频道上设置或映射MCAUSER
,则QMgr将接受您提供的ID,并且不会检查密码。如果MQ管理员配置了通道出口,则退出可以根据LDDAP,AD,本地操作系统等验证密码。但如果没有安装exit,则不检查密码。
既然您知道这一点,您就可以回答有关setDirectAuth
效果的问题(因为我不能)。如果该参数由连接工厂继承并由通道请求声明,则它将被传递给MQ,如果通道不安全,则将被接受。类似地,如果您使用了带有ID和密码的Connection对象构造函数,您可以DEFINITELY断言一个ID,如果该通道不安全,它将被QMgr接受。
您可以使用以下方法对此进行测试:
connection = ConnectionFactory.createConnection('mqm', 'doesntmatter');
如果QMgr在UNIX / Linux上并且不安全,则该应用程序将以mqm
运行。我不建议像这样运行,正确的反应是保护它。但这是一种测试方法,看它是否安全。