ActiveMQ现在无疑成为JMS领域开源产品的龙头,基于开源框架的J2EE开发者大多用它来进行异步数据的传递工作。
比较搞的是截至ActiveMQ4.1.1版本的缺省配置仍然没有做任何的安全性配置,也就是说如果没有在软硬件防火墙层面上做限制的话,任何客户端都可以连接上JMS提供者发送和接收消息!估计大部分开发者用的都是缺省设置吧,呵呵。
当然,ActiveMQ的开发者还不至于弱智到这种程度,连最起码的权限验证都不支持。在org.apache.activemq.security包下面是提供了两种可选验证机制的:用户名/密码Map和JAAS。
无疑,基于JAAS的验证是J2EE规范之一,能实现最大的灵活性配置,不过一般情况下异步发个邮件什么的应用没有必要搞这么复杂。这里关注的是最简单的用户名/密码验证方法,就像JDBC数据源一样。
ActiveMQ服务broker是在activemq.xml中配置的,其本质上也是一个spring bean配置文件。4.0版本以后支持xbean配置方式,典型的配置文件如下:
- <broker brokerName="localhost" useJmx="true">
- <persistenceAdapter>
- <journaledJDBC journalLogFiles="5" dataDirectory="${webapp.root.cn.com.reachway}/WEB-INF/activemq-data"
- dataSource="#derby-ds" />
- </persistenceAdapter>
- <transportConnectors>
- <transportConnector name="openwire" uri="tcp://localhost:61616" discoveryUri="multicast://default" />
- </transportConnectors>
- <networkConnectors>
- <networkConnector name="default-nc" uri="multicast://default" />
- </networkConnectors>
- </broker>
broker实质上就是一个org.apache.activemq.broker.BrokerService实例,可以扩展之以提供简单验证,如下:
- public class ConfigurableAuthenticationBroker extends XBeanBrokerService {
- private String userName = "jms";
- private String password = "password";
- public String getUserName() {
- return userName;
- }
- public void setUserName(String userName) {
- this.userName = userName;
- }
- public String getPassword() {
- return password;
- }
- public void setPassword(String password) {
- this.password = password;
- }
- protected Broker addInterceptors(Broker broker) throws Exception {
- broker = super.addInterceptors(broker);
- Map userPasswordMap = new HashMap();
- userPasswordMap.put(userName, password);
- broker = new SimpleAuthenticationBroker(broker, userPasswordMap, new HashMap());
- return broker;
- }
- }
由于这里采用xbean方式配置,所以扩展的是XBeanBrokerService类。
相应的activemq.xml中的broker配置改为:
- <c:ConfigurableAuthenticationBroker brokerName="localhost" useJmx="true" userName="jms" password="password"
- xmlns:c="java://cn.com.xxx.framework.common.jms">
- <persistenceAdapter>
- <journaledJDBC journalLogFiles="5" dataDirectory="${webapp.root.cn.com.xxx}/WEB-INF/activemq-data"
- dataSource="#derby-ds" />
- </persistenceAdapter>
- <transportConnectors>
- <transportConnector name="openwire" uri="tcp://localhost:61616" discoveryUri="multicast://default" />
- </transportConnectors>
- <networkConnectors>
- <networkConnector name="default-nc" uri="multicast://default" />
- </networkConnectors>
- </c:ConfigurableAuthenticationBroker>
可以看到在bean c:ConfigurableAuthenticationBroker的属性中多了userName和password,于是可配置性便有了。如果想要配置更多的用户可以改成map型了,道理都是一样的。
相应的,JMS客户端在连接时就需要加上用户名和密码属性了,否则就会返回错误:
- javax.jms.JMSException: User name or password is invalid.
- at org.apache.activemq.util.JMSExceptionSupport.create(JMSExceptionSupport.java:46)
- at org.apache.activemq.ActiveMQConnection.syncSendPacket(ActiveMQConnection.java:1181)
- at org.apache.activemq.ActiveMQConnection.ensureConnectionInfoSent(ActiveMQConnection.java:1263)
若是采用的spring管理的JMS资源适配器方式,给适配器bean加上用户名、密码属性即可:
- <bean id="jmsResourceAdapter" class="org.apache.activemq.ra.ActiveMQResourceAdapter">
- <property name="serverUrl" value="tcp://localhost:61616" />
- <property name="userName" value="jms" />
- <property name="password" value="password" />
- </bean>
其实很简单,但也够用了。回头有空再研究下JAAS方式吧:)