当前位置: 首页 > ActiveMQ in Action 读书笔记 > 正文

6.3 创建自定义安全插件

 

6.3 Building a custom security plug-in

So far this chapter has focused on the built-in security features in ActiveMQ. Thoughthese features should provide enough functionality for the majority of users, an evenmore powerful feature is available. As stated previously, the ActiveMQ plug-in API isextremely flexible and the possibilities are endless. The flexibility in this functionalitycomes from the BrokerFilter class. This class provides the ability to intercept manyof the available broker-level operations. Broker operations include such items as addingconsumers and producers to the broker, committing transactions in the broker,and adding and removing connections to the broker, to name a few. Custom functionalitycan be added by extending the BrokerFilter class and overriding a method for agiven operation.

6.3 创建自定义安全插件

 到目前为止,本章讨论的内容都是ActiveMQ自带的安全功能.尽管这些自带的功能已足够绝大多数用户使用,但是ActiveMQ还提供了一种更加强大的功能.前面已经提到,ActiveMQ的插件API具有强大的灵活性,其支持的功能是无穷无尽的.ActiveMQ的灵活性来自于BrokerFilter类的功能.该类提供了一种拦截大多数可用代理的各种操作功能.代理的操作包扩:为代理增加消息生产者和消费者,提交代理的事务,增加/移除到代理的连接,等等.可以通过扩展BrokerFilter类并且为特定的操作覆盖相关的方法来实现自定义功能.

 Though the ActiveMQ plug-in API isn’t concerned solely with security, implementinga class whose main purpose is to handle a custom security feature is achievable. Soif you have security requirements that can’t be met using the previous security features,you may want to consider developing a custom solution for your needs. Dependingon your needs, two choices are available:

 尽管ActiveMQ的插件API不仅仅关注安全机制,但是实现一个主要用于处理自定义安全的类是可行的.因此,如果你有安全方面的需求且该需求不能使用前面介绍的ActiveMQ自带的安全机制来解决,你可以考虑使用自定义功能来实现自己的需求.基于你的需求,有两种方式可供选择:

 Implement a JAAS login module—There’s a good chance that you’re already usingJAAS in your Java applications. In this case, it’s only natural that you’ll try toreuse all that work for securing the ActiveMQ broker, too. Since JAAS isn’t themain topic of this book, we won’t dive any deeper into this topic than wealready have.

 方式一:实现一个JAAS登陆模块 — 如果你已经在你的应用程序中使用JAAS的话,这是一个不错的选择.这种情况下,你可以很自然的想到在ActiveMQ代理中重用已实现的JASS登陆模块.因为JAAS不是本书讨论的主题,我们不打算更深入的介绍JAAS.

 Implement a custom plug-in for handling security—ActiveMQ provides a flexiblegeneric plug-in mechanism. You can create your own custom plug-ins for justabout anything, including custom security plug-ins. So if you have requirementsthat can’t be met by implementing a JAAS module, writing a custom plug-in isthe way to go.

 方式二:实现自定义的插件为处理ActiveMQ安全提供了一个灵活的机制.你可以创建自定义的插件来处理任何事情,当包含自定义的安全插件.因此假如你有一个不能通过实现JAAS登陆模块来完成需求,你可以写一个自定义插件来完成.

 In this section we’ll describe how to write a simple security plug-in that authorizes brokerconnections only from a certain set of IP addresses. The concept isn’t complex butis good enough to give you a taste of the BrokerFilter with an angle toward security.

 本节中我们将介绍如何通过写一个简单的安全插件来限制只有IP地址属于指定IP地址集合的客户端才能连接到代理.这个插件涉及到的概念不是很复杂,但是作为在安全角度尝试BrokerFilter的应用来说已经相当好了.

 6.3.1 Implementing the plug-in

In order to limit connectivity to the broker based on IP address, we’ll create a classnamed IPAuthenticationBroker to override the BrokerFilter.addConnection()method. The implementation of this method will perform a simple check of the IPaddress using a regular expression to determine the ability to connect. The followinglisting shows the implementation of the IPAuthenticationBroker class.

Listing 6.4 IPAuthenticationBroker class—custom broker implementation

 6.3.1 实现插件

为了根据客户端的IP地址来限制到代理的连接,我们创建一个名称为IPAuthenticationBroker的方法以覆盖BrokerFilter.addConnection()方法.该方法中将使用正则表达式简单的检查客户端的IP地址以便决定客户端能否连接到代理.下面是IPAuthenticationBroker方法的代码清单:

清单6.4 IPAuthenticationBroker类 — 实现自定义代理

public class IPAuthenticationBroker extends BrokerFilter 
{
  List<String> allowedIPAddresses;
  Pattern pattern = Pattern.compile("^/([0-9\\.]*):(.*)");
 
  public IPAuthenticationBroker(Broker next, List<String> allowedIPAddresses) 
  {
    super(next);
    this.allowedIPAddresses = allowedIPAddresses;
  }
  
  public void addConnection(ConnectionContext context, ConnectionInfo info) throws Exception 
  {
    String remoteAddress = context.getConnection().getRemoteAddress();
    Matcher matcher = pattern.matcher(remoteAddress);
    if (matcher.matches()) 
    {
      String ip = matcher.group(1);
      if (!allowedIPAddresses.contains(ip)) 
      {
        throw new SecurityException("Connecting from IP address " + ip + " is not allowed" );
      }
    } 
    else 
    {
      throw new SecurityException("Invalid remote address " + remoteAddress);
    }
    super.addConnection(context, info);
  }
}

 The BrokerFilter class defines methods that intercept broker operations such as addinga connection, removing a subscriber, and so forth. In the IPAuthenticationBrokerclass, the addConnection() method is overridden to create some logic that checkswhether the address of a connecting client falls within a list of IP addresses that areallowed to connect. If that IP address is allowed to connect, the call is delegated to theBrokerFilter. addConnection() method. If that IP address isn’t allowed to connect,an exception is thrown.

 BrokerFilter类定义了一些方法,这些方法可以拦截代理的一些操作,比如:增加一个连接,移除一个消息订阅者,等等.在IPAuthenticationBroker类中,addConnection()方法被覆盖了以便创建一些检查客户端IP地址是否在允许IP地址列表之内的逻辑.如果当前的IP地址可以连接到代理,对该方法的调用将转移给BrokerFilter类的addConnection() 方法来处理.如果当前的IP地址不允许连接,则会抛出一个异常.

 One additional item of note in the IPAuthenticationBroker class is that its constructorcalls the BrokerFilter’s constructor. This call serves to set up the chain ofinterceptors so that the proper cascading will take place through the chain. Don’t forgetto do this if you create your own BrokerFilter implementation.

 关于IPAuthenticationBroker类需要额外注意的是,该类的构造函数调用了BrokerFilter类的构造函数.这样调用设置了拦截链,以便建立正确的拦截链级联.在创建你自己的BrokerFilter实现时,不要忘记在构造函数中做这种处理.

 After the actual plug-in logic has been implemented, the plug-in must be configuredand installed. For this purpose, an implementation of the BrokerPlugin will becreated. The BrokerPlugin is used to expose the configuration of a plug-in and alsoto install the plug-in into the ActiveMQ broker. In order to configure and install theIPAuthenticationBroker, the IPAuthenticationPlugin class is created as shown inthe following listing.

Listing 6.5 IPAuthenticationPlugin class—custom plug-in implementation

 当实现了插件的真正逻辑后,还必须要配置和安装插件.为此,需要实现BrokerPlugin,该类用于将一个插件暴露给ActiveMQ代理,以便代理能够安装它.为了配置和安装插件,创建IPAuthenticationPlugin类,其代码如下所示:

清单6.5 IPAuthenticationPlugin类 — 自实现定义插件

public class IPAuthenticationPlugin implements BrokerPlugin 
{
  List<String> allowedIPAddresses;
  public Broker installPlugin(Broker broker) throws Exception 
  {
    return new IPAuthenticationBroker(broker, allowedIPAddresses);
  }
  
  public List<String> getAllowedIPAddresses() 
  {
    return allowedIPAddresses;
  }
  
  public void setAllowedIPAddresses(List<String> allowedIPAddresses) 
  {
    this.allowedIPAddresses = allowedIPAddresses;
  }
}

 The IPAuthenticationBroker.installPlugin() method is used to instantiate theplug-in and return a new intercepted broker for the next plug-in in the chain. Notethat the IPAuthenticationPlugin class also contains getter and setter methods usedto configure the IPAuthenticationBroker. These setter and getter methods are thenavailable via a Spring beans–style XML configuration in the ActiveMQ XML configurationfile (as you’ll see in a moment).

 IPAuthenticationBroker的installPlugin()方法用来初始化插件然后返回一个被拦截的代理,该代理用于拦截链中的下一个插件.需要注意的是,IPAuthenticationPlugin还包含getter和setter方法用于配置IPAuthenticationBroker类–setter和getter方法可用于ActiveMQ的Spring beans风格的XML配置文件(稍后将看到).

 6.3.2 Configuring the plug-in

Now that we’ve implemented the plug-in, let’s see how we can configure it usingthe ActiveMQ XML configuration file. The following listing shows how theIPAuthenticationPlugin class is used in configuration.

Listing 6.6 Configuring the custom plug-in

 6.3.2 配置插件

实现了自定义插件后,让我们再看看如何使用该自定义插件配置ActiveMQ的XML配置文件.下面的配置代码清单中显示了如何在配置文件中配置IPAuthenticationPlugin.

代码清单6.6 自定义插件配置

<broker xmlns="http://activemq.apache.org/schema/core" brokerName="localhost" dataDirectory="${activemq.base}/data">
  <plugins>
    <bean xmlns="http://www.springframework.org/schema/beans" id="ipAuthenticationPlugin" class="org.apache.activemq.book.ch6.IPAuthenticationPlugin">
      <property name="allowedIPAddresses">
        <list>
          <value>127.0.0.1</value>
        </list>
      </property>
    </bean>
  </plugins>
 
  <transportConnectors>
    <transportConnector name="openwire" uri="tcp://localhost:61616" />
  </transportConnectors>
</broker>

 The <broker> element provides the plugins element for declaring plug-ins. Usingthe IPAuthenticationPlugin, only those clients connecting from the IP address127.0.0.1 (the localhost) can actually connect to the broker.

 <broker>元素的plugins子元素用于定义插件.使用IPAuthenticationPlugin插件后,连接到代理的客户端中只有IP地址为127.0.0.1(localhost)的客户端才能连到代理.

 6.3.3 Testing the plug-in

All that needs to be done now is to test the plug-in. Here’s the command to copy theexamples JAR file into place (because it contains the plug-in) and the command tostart up ActiveMQ using the IPAuthenticationPlugin and the IPAuthentication-Broker:

 6.3.3 测试插件

现在要做的就是测试常见了.下面的命令首先,复制示例中的jar包(因为该jar包中含有插件类)到合适的位置,然后启动使用了IPAuthenticationPlugin和IPAuthentication的代理:

$ cp target/activemq-in-action-examples.jar ${ACTIVEMQ_HOME}/lib/

$ {ACTIVEMQ_HOME}/bin/activemq console xbean:src/main/resources/org/apache/activemq/book/ch6/activemq-custom.xml
(译注:window中的命令 %ACTIVEMQ_HOME%/bin/activemq xbean:src/main/resources/org/apache/activemq/book/ch6/activemq-custom.xml)
(译注:使用ActiveMQ5.8测试,原始源码中的配置文件貌似有问题,已改成下面这样:

activemq-custom.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.xsd
  http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd">
<!-- Allows us to use system properties as variables in this configuration file -->
    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" />
 
	<broker xmlns="http://activemq.apache.org/schema/core"
	brokerName="localhost" dataDirectory="${activemq.base}/data" >
	 
	<!-- The transport connectors ActiveMQ will listen to -->
	<transportConnectors>
	<transportConnector name="openwire"
	uri="tcp://localhost:61616" />
	</transportConnectors>
		
		<plugins>
		  <bean xmlns="http://www.springframework.org/schema/beans" id="ipAuthenticationPlugin" class="org.apache.activemq.book.ch6.IPAuthenticationPlugin">
			<property name="allowedIPAddresses">
			  <list>
				<value>127.0.0.1</value>
			  </list>
			</property>
		  </bean>
		</plugins>
	  
	</broker>
</beans>

)

...
Loading message broker from: xbean:src/main/resources/org/apache/activemq/book/ch6/activemq-custom.xml
...
23:22:46,982 | INFO | PListStore:/Users/bsnyder/amq/apache-activemq-5.4.1/data/localhost/tmp_storage started
23:22:47,156 | INFO | JMX consoles can connect to service: jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi
23:22:47,159 | INFO | Using Persistence Adapter: KahaDBPersistenceAdapter[/Users/bsnyder/amq/apache-activemq-5.4.1/data/localhost/KahaDB]
23:22:48,033 | INFO | KahaDB is version 2
23:22:48,083 | INFO | ActiveMQ 5.4.1 JMS Message Broker (localhost) isstarting
23:22:48,084 | INFO | For help or more information please see:http://activemq.apache.org/
23:22:48,234 | INFO | Scheduler using directory:/Users/bsnyder/amq/apache-activemq-5.4.1/data/localhost/scheduler
23:22:48,275 | INFO | JobSchedulerStore:/Users/bsnyder/amq/apache-activemq-5.4.1/data/localhost/scheduler started
23:22:48,317 | INFO | Listening for connections at: tcp://localhost:61616
23:22:48,317 | INFO | Connector openwire Started
23:22:48,319 | INFO | ActiveMQ JMS Message Broker
(localhost, ID:mongoose.local-49947-1289974968106-0:0) started
...

 Now run the client to connect to ActiveMQ from the localhost and everything shouldbe working fine. See the following output:

 接着,使用下面的命令,在localhost上运行客户端以连接到ActiveMQ,程序运行应该一切正常.命令后面面是程序输出信息:

$mvn exec:java -Dexec.mainClass=org.apache.activemq.book.ch3.portfolio.Publisher -Dexec.args="CSCO ORCL"
...
Sending: {price=0.7137712112409276, stock=ORCL, offer=0.7144849824521684,up=true} on destination: topic://STOCKS.ORCL
Sending: {price=0.7127548328743109, stock=ORCL, offer=0.7134675877071851,up=false} on destination: topic://STOCKS.ORCL
Sending: {price=0.710497871629952, stock=ORCL, offer=0.711208369501582,up=false} on destination: topic://STOCKS.ORCL
Sending: {price=0.7167766362460622, stock=ORCL, offer=0.7174934128823083,up=true} on destination: topic://STOCKS.ORCL
Sending: {price=54.586310464064766, stock=CSCO, offer=54.64089677452883,up=false} on destination: topic://STOCKS.CSCO
Sending: {price=54.45678231194236, stock=CSCO, offer=54.5112390942543,up=false} on destination: topic://STOCKS.CSCO
Sending: {price=0.7134830573922482, stock=ORCL, offer=0.7141965404496403,up=false} on destination: topic://STOCKS.ORCL
Sending: {price=0.7125898470778729, stock=ORCL, offer=0.7133024369249507,up=false} on destination: topic://STOCKS.ORCL
Sending: {price=0.7106363691848542, stock=ORCL, offer=0.711347005554039,up=false} on destination: topic://STOCKS.ORCL
Sending: {price=54.99339386523512, stock=CSCO, offer=55.04838725910035,up=true} on destination: topic://STOCKS.CSCO
Published '10' of '10' price messages
...

 If a connection attempt is made from any host other than the localhost, you canexpect to see the following output including the exception:

 如果有非localhost的客户端尝试连接到代理,你将看到下面的输出中显示的异常信息:

$ mvn exec:java -Dexec.mainClass=org.apache.activemq.book.ch3.portfolio.Publisher -Dexec.args="CSCO ORCL"
...
Exception in thread "main"
javax.jms.JMSException: Connecting from IP address 192.168.10.10 is not allowed
...

  Although this example was more complex, it serves as a good demonstration of thepower provided by the BrokerFilter class. Just imagine how flexible this plug-inmechanism is for integrating with existing custom security requirements. This examplewas focused on a security example, but many other operations can be customizedby using the pattern illustrated here.

 这个例子更加复杂一些,用它来示例BrokerFilter类提供的强大功能十分合适.可以设想一下使用这种插件机制来集成各种自定义的安全需求是多么的灵活.这个例子仅仅关注安全方面的内容,然而使用这种插件模式可以进行更多的自定义操作.

赞 赏

   微信赞赏  支付宝赞赏


本文固定链接: https://www.jack-yin.com/coding/translation/activemq-in-action/1089.html | 边城网事

该日志由 边城网事 于2013年10月28日发表在 ActiveMQ in Action 读书笔记 分类下, 你可以发表评论,并在保留原文地址及作者的情况下引用到你的网站或博客。
原创文章转载请注明: 6.3 创建自定义安全插件 | 边城网事
关键字: , , ,

6.3 创建自定义安全插件 暂无评论

发表评论

快捷键:Ctrl+Enter