消息队列用的是:apache active MQ,版本:5.5.0
运行环境:服务器是linux
JMS的基本知识这里就不介绍了,直接切入正题。
业务规则是:有一个审计服务器,用来纪录各个应用系统用户的操作等信息,对用户行为进行审计。
这就要求做成一个低耦合的系统,实现这个有很多种,最简单的要属于直接url请求,但是安全性、请求丢失等无法保证,而且请求一般是request/response,这中间网络传输会延迟系统,不是很好的。Web Service框架没有仔细研究,不过记得金蝶中间件讲解他们的ESB的时候,同构的系统(Java EE)用的是JMS,异构的系统用的是Web Service实现。基于这种原因,选用了JMS。
基本架构是这样的,各个应用程序为消息(Message)的生产者,生产的消息中包含审计信息。审计服务器是消费的消费者,纪录获取到的审计信息。
审计端的配置如下:
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:amq="http://activemq.org/config/1.0"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://activemq.org/config/1.0
http://activemq.apache.org/schema/activemq-core.xsd">
<-- JMS连接池塘 -->
<bean id="jmsFactory" class="org.apache.activemq.pool.PooledConnectionFactory"
destroy-method="stop">
<property name="connectionFactory">
<bean class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL">
<value>tcp://localhost:61616</value>
</property>
<property name="userName">
<value>guest</value>
</property>
<property name="password">
<value>password</value>
</property>
</bean>
</property>
</bean>
<bean id="myJmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory">
<ref local="jmsFactory" />
</property>
</bean>
<bean id="javaDest" class="org.apache.activemq.command.ActiveMQQueue" autowire="constructor">
<constructor-arg value="AUDIT.DPPC" />
</bean>
<!-- 审计监听者,用来对消费的消息进行处理 -->
<bean id="auditListener" class="org.dppc.jms.AuditListener">
<constructor-arg ref="jmsAuditServer"></constructor-arg>
</bean>
<!-- 审计逻辑 -->
<bean id="jmsAuditServer" class="org.dppc.audit.server.impl.JMSAuditServer">
</bean>
<bean id="javaConsumer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="jmsFactory"/>
<property name="destination" ref="javaDest" />
<property name="messageListener" ref="auditListener" />
</bean>
</beans>
客户端也很简单
public class AuditProductor {
private static transient ConnectionFactory factory;
private transient Connection connection;
private transient Session session;
private transient MessageProducer producer;
public AuditProductor() throws JMSException {
//建立AMQ连接的消费很高,应该用连接池什么的,客户端代码,暂时这样
factory = new ActiveMQConnectionFactory(AuditConfig.getUserName(), AuditConfig.getPassword(), AuditConfig.getBrokerUrl());
connection = factory.createConnection();
connection.start();
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Destination destination = session.createQueue(AuditConfig.getDestination());
producer = session.createProducer(destination);
}
public void close() throws JMSException {
if (connection != null) {
connection.close();
}
}
public void sendMessage(AuditDTO auditDTO) throws JMSException {
Message message = session.createObjectMessage(auditDTO);
producer.send(message);
}
}
AMQ配置
bitlanghen@team1:~$ cat /srv/amq/apache-activemq-5.5.0/conf/activemq-security.xml
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!--
Secure ActiveMQ broker
For more information, see:
http://activemq.apache.org/security.html
Before you can run this configuration, you need to set ACTIVEMQ_ENCRYPTION_PASSWORD environment variable, like
$ export ACTIVEMQ_ENCRYPTION_PASSWORD=activemq
For more information see: http://activemq.apache.org/encrypted-passwords.html
To run ActiveMQ with this configuration add xbean:conf/activemq-security.xml to your command
e.g. $ bin/activemq console xbean:conf/activemq-security.xml
-->
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:amq="http://activemq.apache.org/schema/core"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd">
<!-- Allows us to use encrypted system properties as variables in this configuration file -->
<bean id="environmentVariablesConfiguration" class="org.jasypt.encryption.pbe.config.EnvironmentStringPBEConfig">
<property name="algorithm" value="PBEWithMD5AndDES" />
<property name="passwordEnvName" value="ACTIVEMQ_ENCRYPTION_PASSWORD" />
</bean>
<bean id="configurationEncryptor" class="org.jasypt.encryption.pbe.StandardPBEStringEncryptor">
<property name="config" ref="environmentVariablesConfiguration" />
</bean>
<bean id="propertyConfigurer" class="org.jasypt.spring.properties.EncryptablePropertyPlaceholderConfigurer">
<constructor-arg ref="configurationEncryptor" />
<property name="location" value="file:${activemq.base}/conf/credentials-enc.properties"/>
</bean>
<!--
Use this configuration if you don't want to set encryptor password using environment variable
Note however, that with this solution your passwords can be easily decrypted once the encrypter password is known
<bean id="configurationEncryptor" class="org.jasypt.encryption.pbe.StandardPBEStringEncryptor">
<property name="algorithm" value="PBEWithMD5AndDES"/>
<property name="password" value="activemq"/>
</bean>
-->
<broker useJmx="true" persistent="false" xmlns="http://activemq.apache.org/schema/core" destroyApplicationContextOnStop="true">
<managementContext>
<managementContext createConnector="true">
<property xmlns="http://www.springframework.org/schema/beans" name="environment">
<map xmlns="http://www.springframework.org/schema/beans">
<entry xmlns="http://www.springframework.org/schema/beans" key="jmx.remote.x.password.file"
value="conf/jmx.password"/>
<entry xmlns="http://www.springframework.org/schema/beans" key="jmx.remote.x.access.file"
value="conf/jmx.access"/>
</map>
</property>
</managementContext>
</managementContext>
<plugins>
<!-- Configure authentication; Username, passwords and groups -->
<simpleAuthenticationPlugin>
<users>
<authenticationUser username="system" password="${activemq.password}"
groups="users,admins"/>
<authenticationUser username="user" password="${guest.password}"
groups="users"/>
<authenticationUser username="guest" password="${guest.password}" groups="guests"/>
</users>
</simpleAuthenticationPlugin>
<!-- Lets configure a destination based authorization mechanism -->
<authorizationPlugin>
<map>
<authorizationMap>
<authorizationEntries>
<authorizationEntry queue=">" read="admins" write="admins" admin="admins" />
<authorizationEntry queue="USERS.>" read="users" write="users" admin="users" />
<authorizationEntry queue="GUEST.>" read="guests" write="guests,users" admin="guests,users" />
<authorizationEntry queue="AUDIT.>" read="guests" write="guests,users" admin="guests,users" />
<authorizationEntry queue="TEST.Q" read="guests" write="guests" />
<authorizationEntry topic=">" read="admins" write="admins" admin="admins" />
<authorizationEntry topic="USERS.>" read="users" write="users" admin="users" />
<authorizationEntry topic="GUEST.>" read="guests" write="guests,users" admin="guests,users" />
<authorizationEntry topic="ActiveMQ.Advisory.>" read="guests,users" write="guests,users" admin="guests,users"/>
</authorizationEntries>
</authorizationMap>
</map>
</authorizationPlugin>
</plugins>
<transportConnectors>
<transportConnector name="default" uri="tcp://0.0.0.0:61616"/>
</transportConnectors>
</broker>
<!--
Configure command agent to be used in secured broker environment
Notice how we used ${activemq.username} and ${activemq.password} configured in credential.properties
-->
<commandAgent xmlns="http://activemq.apache.org/schema/core" brokerUrl="vm://localhost" username="${activemq.username}" password="${activemq.password}"/>
<!-- Use Web applications and Camel in secured broker environment -->
<import resource="jetty.xml"/>
<import resource="camel.xml"/>
</beans>
中间添加了一个审计的目标(destination)权限<authorizationEntry queue="AUDIT.>" read="guests" write="guests,users" admin="guests,users" />。
最后修改密码,命令
bin/activemq encrypt --password activemq --input mypassword
...
Encrypted text: eeWjNyX6FY8Fjp3E+F6qTytV11bZItDp
然后在${activemq.base}/conf/credentials-enc.properties中修改密码,替换ENC($password)中的password,就可以正常运行了