'setDirectAuth'是IBM MQ连接工厂身份验证问题的有效解决方案(RC 2035)

时间:2012-10-10 15:11:10

标签: spring ibm-mq

我需要连接到我的应用程序中的远程队列,但是当在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   --> 

1 个答案:

答案 0 :(得分:1)

当您的应用打开本地队列时,授权配置文件会与打开的队列名称相匹配。换句话说,如果连接到LOCALQMGR的应用打开SYSTEM.DEF.LOCAL.QUEUE@LOCALQMGRLOCALQMGR上的授权控制列表条目必须授予应用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运行。我不建议像这样运行,正确的反应是保护它。但这是一种测试方法,看它是否安全。