ActiveMQ in Action 翻译

来源:互联网 发布:macbook装office软件 编辑:程序博客网 时间:2024/05/21 11:12

6      第六章 Securing ActiveMQ

本章内容:

n  在ActiveMQ中如何Authentication

n  在ActiveMQ中如何Authorization

n  如何为ActiveMQ创建自定义安全插件

n  配置ActiveMQ使用第三方认证系统

  安全访问message broker和destinations 是普遍的需求。因此,ActiveMQ提供了灵活的可自定义的安全模型来使其能够和你所使用的安全框架融合。

  在我们讨论ActiveMQ的安全模型之前,需要了解一些关于安全的概念以及这些概念在ActiveMQ中是如何体现的。

 Authentication是指“验证访问受保护资源的实体或用户是真正用户的过程”。一般的验证表单包括:密码、一次性密码策略、智能卡等等。ActiveMQ提供简单的authentication和JAAS(Java Authenticaitn and Authorization Service) authentication,并提供接口来编写自定义authentication插件。基于成功的authentication,用户被允许登陆系统,但是使用系统资源完成特定的操作还是需要指定的authorization。

 Authorization是指“验证用户是否有足够的权限访问受保护资源的过程”。Authentication决定用户是否可以登陆系统,authorization基于authentication决定用户使用可以执行某些操作。例如:用户X是否有足够的权限在系统Z上执行Y程序?类似的权限通常被定义成access control list (ACLs)来决定谁或者什么可以接近资源并执行哪些操作。在ActiveMQ中,Authentication包括:publish to a destination,consume from a destination,create adestination,delete a destination。

  在本章的开始我们会描述authentication插件。我们会演示如何使用simple authenticationplugin或者JAAS API通过XML配置文件来配置authentication,是时候来处理authorization了。我们会描述authorization插件,它会和authentication插件一起帮助我们建立一套完整的访问broker 客户端的安全系统。除了这种标准的per-client authorization,ActiveMQ允许我们在message level做authorization。如果这些内置的安全框架无法满足你的要求,你也可以创建你自己的。我们通过创建一个自定义安全插件来演示这个过程,这个插件通过客户端的IP地址来验证它们的权限。本章的最后一个小节会处理certificate-based安全框架。我们会展开介绍在第四章中的SSL例子,来告诉你如何通过SSLcertificates来authenticate和authorize客户端。

  所以,当阅读完本章后,你会知道如何保护你的broker并且和你现存的安全框架完美融合。下面我们一起来看看ActiveMQ安全配置的例子。

6.1      Authentication

ActiveMQ中关于安全的概念都是通过插件来实现。我们可以在ActiveMQ XML文件中通过<plugin>元素来配置并实现自定义。目前在ActiveMQ中可以使用两种插件:

n  Simple authentication plug-in:在XML或properties文件中直接配置安全策略

n  JAAS authentication plug-in:实现JAAS API,提供强大的并可自定义的authentication解决方案

下面我们就来看看这两个authentication插件。

6.1.1       配置Simple authentication 插件

保护broker的最简单的方式是在broker的XML配置文件中定义authentication策略。这些功能是ActiveMQ中的simple authentication插件提供的。下面的代码是这个插件的使用例子。

 

Listing 6.1 Configuring the simpleauthentication plug-in

<broker ...>

<plugins>

<simpleAuthenticationPlugin>

<users>

<authenticationUserusername="admin" password="password"

groups="admins,publishers,consumers"/>

<authenticationUserusername="publisher" password="password"

groups="publishers,consumers"/>

<authenticationUserusername="consumer" password="password"

groups="consumers"/>

<authenticationUserusername="guest" password="password"

groups="guests"/>

</users>

</simpleAuthenticationPlugin>

</plugins>

</broker>

通过使用上面的代码段,四个用户就可以访问ActiveMQ。明显的,为了authentication,每个用户必须定义username和password。另外,属性groups表面用户属于哪个group。这个属性是为authorization准备的,这将在后面介绍。

  理解这些配置的最好方式是在stock portfolio例子使用它们。首先,broker必须使用这些配置并已经启动。

${ACTIVEMQ_HOME}/bin/activemq console \

xbean:src/main/resources/org/apache/activemq/book/ch6/activemq-simple.xml

现在运行stockpublisher,你会看到下面的异常:

$ mvn exec:java \

-Dexec.mainClass=org.apache.activemq.book.ch3.portfolio.Publisher\

-Dexec.args="CSCO ORCL"

...

Exception in thread "main"

javax.jms.JMSException: User name or password isinvalid.

...

这些异常是我们可以预料到的,因为我们使用了安全插件,但是我们并没有给publisher添加authentication credentials。给publisher添加用户名和密码就可以解决这个异常。如下面代码所示:

private String username = "publisher";

private String password = "password";

public Publisher() throws JMSException {

factory = new ActiveMQConnectionFactory(brokerURL);

connection = factory.createConnection(username,password);

connection.start();

session = connection.createSession(false,

Session.AUTO_ACKNOWLEDGE);

producer = session.createProducer(null);

}

如上代码所示,唯一的变化就是在createConnection()方法中定义了用户名和密码。编译并运行修改后的publisher就会得到正确的结果,如下所示:

$ mvn exec:java \

-Dexec.mainClass=org.apache.activemq.book.ch6.Publisher

-Dexec.args="CSCO ORCL"

...

Sending: {price=35.25020234334, stock=ORCL,offer=35.28545254568,

up=true} on destination: topic://STOCKS.ORCL

Sending: {price=35.018408299624, stock=ORCL,offer=35.053426707924,

up=false} on destination: topic://STOCKS.ORCL

Sending: {price=34.722966908601, stock=ORCL,offer=34.75768987551,

up=false} on destination: topic://STOCKS.ORCL

Sending: {price=1.651542629939308, stock=CSCO,offer=1.653194172569,

up=true} on destination: topic://STOCKS.CSCO

Sending: {price=34.598719623046, stock=ORCL,offer=34.63331834266,

up=false} on destination:topic://STOCKS.ORCL

Sending: {price=34.43900856142, stock=ORCL,offer=34.47344756998,

up=false} on destination: topic://STOCKS.ORCL

Sending: {price=1.6580787335090, stock=CSCO,offer=1.659736812242,

up=true} on destination: topic://STOCKS.CSCO

Sending: {price=34.458768559093, stock=ORCL,offer=34.49322732765,

up=true} on destination: topic://STOCKS.ORCL

Sending: {price=1.6547727745488, stock=CSCO,offer=1.6564275473233,

up=false} on destination:topic://STOCKS.CSCO

Sending: {price=1.665375738897, stock=CSCO,offer=1.6670411146368,

up=true} on destination: topic://STOCKS.CSCO

Published '10' of '10' price messages

...

 

上面代码显示我们已经成功连接到了broker并发送了信息。

  不幸的是,simple authentication插件会明文保存/发送密码,这将影响broker的安全性。另外,如果在使用simple authentication时使用SSL传输,就可以解决在网络上传输明文密码的问题。

  对于需要更安全的系统或者已经存在安全框架的情况下,JAAS插件更能满足需要。

 

6.1.2       配置JAAS插件

本书不会详细介绍JAAS。本小节将介绍JAAS的基础概念并实现一个Properties-LoginModule的例子,这个例子与上节简单插件实现的功能相同。如果想了解关于JAAS的详细信息,请阅读JAAS相关文档(http://mng.bz/BvvB)。

  JAAS提供pluggableauthentication,这说明ActiveMQ只会使用一套authenticationAPI而不会关心验证用户证书的具体方法(文本,关系数据库,LDAP等等)。唯一要做的是实现javax.security.auth.spi.LoginModule接口(http://mng.bz/8zLV )并提供一组配置文件。ActiveMQ内部已经实现了一些接口。这些接口可以通过properties文件、LDAP、SSLcertificates验证用户证书来满足普通用户的需要。因为JAASlogin modules有详细的说明,所以配置非常简单。了解loginmodule最好的方式就是实践一次。下面我们就通过配置文件来实现一个loginmodule。

  第一步是定义PropertiesLoginModule并使其能够被ActiveMQ感知。所以我们新建一个名为login.config的文件,文件中包含配置JAAS的users和groups格式化信息(http://mng.bz/IIEB)。下面是文件内容:

activemq-domain {

org.apache.activemq.jaas.PropertiesLoginModule required

debug=true

org.apache.activemq.jaas.properties.user="users.properties"

org.apache.activemq.jaas.properties.group="groups.properties";

};

 

如上内容定义了一些JAASmodule相关的条目。activemq-domain作为顶级目录包含了所有的配置信息。第一个元素是PropetiesLoginModule的全路径名称,后面跟了“required”标记。这意味着如果没有这个login module,authentication过程就不会继续。第二个是允许login module进行debug日志记录。着是一个可选项。第三个是org.apache.activemq.jaas.properties.user属性,这个属性指向了users.properties文件,第四个是org.apache.activemq.jaas.properties.group属性,这个属性指向了groups.properties文件。一旦这些属性被定义,那么这两个属性文件也必须存在。

NOTE 上文的PropertiesLoginModule是JAAS LOGIN MODULE的一个实现,它和ActiveMQ一起发布。

  在属性文件中定义用户证书非常简单。在users.properties文件中,每一行定义了一个用户及其密码,用等号连接。如下所示:

admin=password

publisher=password

consumer=password

guest=password

在groups.properties文件中每一行定义了一个group及其成员,每个成员名称已“,”分割。如下所示:

admins=admin

publishers=admin,publisher

consumers=admin,publisher,consumer

guests=guest

这些文件创建完成后,ActiveMQXML配置文件中就必须定义JAAS插件。如下:

...

<plugins>

<jaasAuthenticationPluginconfiguration="activemq-domain" />

</plugins>

...

为了便于阅读,这个例子已经被缩减并且只保存了实现JAAS login module必要的信息。像你所看到的一样,JAAS插件只需要login.config文件中定义的JAAS domain的名称。ActiveMQ会根据classpath来定位login.config文件的位置(可选的是通过系统属性java.security.auth.login.config 来定义login.config文件的位置)。未了验证我们创建的JAASlogin module,我们可以按如下所示启动ActiveMQ:

${ACTIVEMQ_HOME}/bin/activemq console \

-Djava.security.auth.login.config=\

src/main/resources/org/apache/activemq/book/ch6/login.config\

xbean:src/main/resources/org/apache/activemq/book/ch6/activemq-jaas.xml

...

Loading message broker from:

xbean:src/main/resources/org/apache/activemq/book/ch6/activemq-jaas.xml

INFO | PListStore:

/Users/bsnyder/amq/apache-activemq-5.4.1/data/localhost/tmp_storage

started

INFO | Using Persistence Adapter:KahaDBPersistenceAdapter

[/Users/bsnyder/amq/apache-activemq-5.4.1/data/localhost/KahaDB]

INFO | JMX consoles can connect to service:

jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi

INFO | ActiveMQ 5.4.1 JMS Message Broker (localhost) isstarting

INFO | For help or more information please see:

http://activemq.apache.org/

INFO | Scheduler using directory:

/Users/bsnyder/amq/apache-activemq-5.4.1/data/localhost/scheduler

INFO | JobSchedulerStore:

/Users/bsnyder/amq/apache-activemq-5.4.1/data/localhost/scheduler

started

INFO | Listening for connections at:tcp://localhost:61616

INFO | Connector openwire Started

INFO | ActiveMQ JMS Message Broker

(localhost,ID:mongoose.local-61955-1289966951514-0:0) started

 

上述改变会像之前章节介绍的simpleauthentication一样保护broker。现在我们可以启动stock portfolio publisher,使用正确的用户证书来访问broker:

mvn exec:java \

-Dexec.mainClass=org.apache.activemq.book.ch6.Publisher\

-Dexec.args="CSCO ORCL"

...

Sending: {price=44.84266119470, stock=ORCL,offer=44.88750385590,

up=true} on destination: topic://STOCKS.ORCL

Sending: {price=44.5575471806, stock=ORCL,offer=44.60210472778,

up=false} on destination: topic://STOCKS.ORCL

Sending: {price=44.49794307251, stock=ORCL,offer=44.54244101559,

up=false} on destination: topic://STOCKS.ORCL

Sending: {price=44.48574009628, stock=ORCL,offer=44.530225836380,

up=false} on destination: topic://STOCKS.ORCL

Sending: {price=55.89763705357, stock=CSCO,offer=55.953534690630,

up=true} on destination: topic://STOCKS.CSCO

Sending: {price=44.09643970531, stock=ORCL,offer=44.140536145020,

up=false} on destination: topic://STOCKS.ORCL

Sending: {price=44.20879151845, stock=ORCL, offer=44.25300030997,

up=true} on destination: topic://STOCKS.ORCL

Sending: {price=44.38257378288, stock=ORCL,offer=44.426956356664,

up=true} on destination: topic://STOCKS.ORCL

Sending: {price=44.660334580924, stock=ORCL,offer=44.704994915505,

up=true} on destination: topic://STOCKS.ORCL

Sending: {price=44.77852477644, stock=ORCL,offer=44.8233033012,

up=true} on destination: topic://STOCKS.ORCL

Published '10' of '10' price messages

...

如上所示,JAAS 插件实现的功能和simple authentication插件一样。区别是它是通过标准的JAVA协议来完成的,这就意味着你可以将公司中的安全策略完美的嵌入其中。

  为了能够控制访问broker服务的权限,ActiveMQ也提供了授权特定操作的能力。下一节我们将关注这个主题。

 

 

6.2      Authorization

  在authentication的基础上,考虑到更细致的控制客户端访问权限的需要。在大多数的股票交易系统中,只有特殊的应用可以像指定的destination输出信息。所以,你不希望一些老的应用向STOCKS.* destination发布股票价格。所以只有authenticated和authorized的应用可以拥有这个权利。

  因为这个原因,ActiveMQ提供了两个级别的authorization:operation-level authorization和message-level authorization。这两个authorization类别提供了比simple authentication更详细的权限控制。这个小节我们会讨论着两种authorization并通过一些例子来学习他们。

 

6.2.1       Destination-level authorization

对于JMSdestination,用户级别的操作有三个:

n  Read:从destination接收消息

n  Write:发送消息到destination

n  Admin:管理destination

通过这些众所周知的操作,你可以控制所以操作的能力。在ActiveMQ XML文件中,这些authorization可以方便的定义。下面代码为destination定义了基于操作的具体的authorization。

 

Listing 6.2 Configuring destination-levelauthorization

...

<plugins>

<jaasAuthenticationPlugin

configuration="activemq-domain" />

<authorizationPlugin>

<map>

<authorizationMap>

<authorizationEntries>

<authorizationEntry topic=">"

read="admins" write="admins"admin="admins" />

<authorizationEntry topic="STOCKS.>"

read="consumers" write="publishers"

admin="publishers" />

<authorizationEntry topic="STOCKS.ORCL"

read="guests" />

<authorizationEntrytopic="ActiveMQ.Advisory.>"

read="admins,publishers,consumers,guests"

write="admins,publishers,consumers,guests"

admin="admins,publishers,consumers,guests"/>

</authorizationEntries>

</authorizationMap>

</map>

</authorizationPlugin>

</plugins>

...

在代码中,JAASauthorization插件已经被定义并指向了login.config文件中的activemq-domain配置。并且被定义了一些authorization entries映射。定义authorization entries映射时,首先要做的是定义受保护的destination。既可以是Topic类型也可以是Queue类型的entry。下一步要做的是声明哪些用户或组可以有权利对destination执行操作。

  在定义destination时可以使用通配符。例如,STOCKS.>意味着所有已STOCKS开头的destination都使用同一套安全策略。第十一章会详细介绍通配符的使用。另外,用户列表既可以是单个用户或者是逗号分隔的用户列表。

  根据这些说明,这个配置文件可以按如下解释:

n  admins组中的所有用户有所有的权限访问所有的topics

n  Consumers能够接收来自STOCKS开头的所有destination的消息,publishers可以向所有STOCKS开头的destination发送消息

n  Guests只能够接收来自STOCKS.ORCLtopic的消息

上述例子中,权限控制类型与添加剂,所有topic的操作都被明确绑定给administrators。处理这些,特定destination上的特定操作被按需分配。

  通过下面的代码来启动broker,测试JAAS authentication插件和authorization entries。

${ACTIVEMQ_HOME}/bin/activemq console \

-Djava.security.auth.login.config=\

src/main/resources/org/apache/activemq/book/ch6/login.config

xbean:src/main/resources/org/apache/activemq/book/ch6/\

activemq-authorization.xml

...

xbean:src/main/resources/org/apache/activemq/book/ch6/\

activemq-authorization.xml

INFO | PListStore:

/Users/bsnyder/amq/apache-activemq-5.4.1/data/localhost/tmp_storage

started

INFO | Using Persistence Adapter:KahaDBPersistenceAdapter

[/Users/bsnyder/amq/apache-activemq-5.4.1/data/localhost/KahaDB]

INFO | JMX consoles can connect to service:

jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi

INFO | ActiveMQ 5.4.1 JMS Message Broker (localhost) isstarting

INFO | For help or more information please see:

http://activemq.apache.org/

INFO | Scheduler using directory:

/Users/bsnyder/amq/apache-activemq-5.4.1/data/localhost/scheduler

INFO | JobSchedulerStore:

/Users/bsnyder/amq/apache-activemq-5.4.1/data/localhost/scheduler

started

INFO | Listening for connections at:tcp://localhost:61616

INFO | Connector openwire Started

INFO | ActiveMQ JMS Message Broker

(localhost,ID:mongoose.local-62861-1289968271876-0:0) started

 

注意系统属性java.security.auth.login.config指出了login.config文件的位置。这保证了ActiveMQ可以正确定位文件的位置。

  现在我们看看如何实现客户端。我们的客户端将尝试从topics中接收消息。就像前面章节我们对publisher客户端做的一样,我们修改原来的stock portfolioconsumer让其通过用户名密码连接到broker。例如,为了让其能够以guest从STOCKS.ORCL接收消息,我们需要添加如下代码:

... private String username = "guest";

private String password = "password";

public Consumer() throws JMSException {

factory = new ActiveMQConnectionFactory(brokerURL);

connection = factory.createConnection(username,password);

connection.start();

session =

connection.createSession(false,Session.AUTO_ACKNOWLEDGE);

}

...

修改过的consumer可以在org.apache.activemq.book.ch6.Consumer类中找到。现在我们允许例子并看到authorization配置是如何影响客户端的。首先用如下代码启动:

$ mvn exec:java \

-Dexec.mainClass=org.apache.activemq.book.ch6.Publisher\

-Dexec.args="CSCO ORCL"

...

Sending: {price=24.07337784180, stock=ORCL,offer=24.0974512196,

up=true} on destination: topic://STOCKS.ORCL

Sending: {price=73.49647952723, stock=CSCO,offer=73.5699760067,

up=false} on destination: topic://STOCKS.CSCO

Sending: {price=24.282731805343, stock=ORCL,offer=24.307014537149,

up=true} on destination: topic://STOCKS.ORCL

Sending: {price=74.1916498091, stock=CSCO,offer=74.265841458,

up=true} on destination: topic://STOCKS.CSCO

Sending: {price=24.350683304888, stock=ORCL,offer=24.375033988192,

up=true} on destination: topic://STOCKS.ORCL

Sending: {price=24.46113711010, stock=ORCL,offer=24.485598247216,

up=true} on destination: topic://STOCKS.ORCL

Sending: {price=24.219079287873, stock=ORCL,offer=24.243298367160,

up=false} on destination: topic://STOCKS.ORCL

Sending: {price=24.282977831328, stock=ORCL,offer=24.307260809160,

up=true} on destination: topic://STOCKS.ORCL

Sending: {price=24.33344653108, stock=ORCL,offer=24.35777997761,

up=true} on destination: topic://STOCKS.ORCL

Sending: {price=73.86498266780, stock=CSCO,offer=73.93884765047,

up=false} on destination: topic://STOCKS.CSCO

Published '10' of '10' price messages

...

现在我们来看看如果用guest用户访问不同的destination会发生什么。例如,如果你试图从STOCKS.CSCO topic接收消息,你会看到如下异常信息:

$ mvn exec:java \

-Dexec.mainClass=org.apache.activemq.book.ch6.Consumer \

-Dexec.args="STOCKS.CSCO"

...

Exception in thread "main"

javax.jms.JMSException: User guest is not authorized toread from:

topic://STOCKS.CSCO...

 

这和我们预期的相同。因为在6.2配置文件中指出从STOCKS.CSCO接收消息是被禁止的。但是允许guest从STOCKS.ORCL接收信息,如下:

$ mvn exec:java \

-Dexec.mainClass=org.apache.activemq.book.ch6.Consumer \

-Dexec.args="STOCKS.ORCL"

...

ORCL 9.66 9.67 down

ORCL 9.70 9.71 up

ORCL 9.80 9.81 up

ORCL 9.83 9.84 up

ORCL 9.80 9.81 down

ORCL 9.75 9.76 down

ORCL 9.81 9.82 up

ORCL 9.88 9.89 up

ORCL 9.80 9.81 down

ORCL 9.84 9.85 up

ORCL 9.84 9.85 up

ORCL 9.86 9.87 up

ORCL 9.95 9.96 up

ORCL 10.03 10.04 up

ORCL 10.03 10.04 down

...

如上所示,authorization配置只允许guests组中的用户从STOCKS.ORCL读取消息。

  这些例子说明保护ActiveMQ destination并对不同的用户分配不同的权限是很简单的。但是,如果对destination的权限控制无法满足你的需要怎么办呢?幸运的是ActiveMQ也支持消息级别的authorization。

 

6.2.2       Message-level authorization

 

到目前为止,我们已经介绍了broker级别的authentication和authorization。但是如你所见,authorization在当试图连接到broker的时候就产生了结果。在一些情况下,我们只希望authorizedestination中的部分信息。在这一节中,我们体验一些消息级别的authorization。

  我们将实现一个简单的authorization插件,这个插件只允许和broker在一个IP地址的应用接收消息。首先我们实现org.apache.activemq.security.MessageAuthorizaitonPolicy接口,如下所示:

Listing 6.3 Implementation ofMessageAuthorizationPolicy interface

public class AuthorizationPolicy implementsMessageAuthorizationPolicy {

private static final Log LOG =

LogFactory.getLog(AuthorizationPolicy.class);

public boolean isAllowedToConsume(ConnectionContextcontext, Message message) {

LOG.info(context.getConnection().getRemoteAddress());

String remoteAddress =context.getConnection().getRemoteAddress();

if (remoteAddress.startsWith("/127.0.0.1")) {

LOG.info("Permission to consume granted");

return true;

} else {

LOG.info("Permission to consume denied");

return false;

}

}

}

如上代码所示,MessageAuthorizationPolicy接口非常简单,仅含有一个方法isAllowedToConsume()。该方法可以拿到消息及连接的上下文。在这个例子中,利用到了连接中的IP地址(通过请求方法Connection.getRemoteAddress),这个地址用来区分请求是来自远程的consumer还是本地的consumer。然后方法isAllowedToConsume()返回是否允许consumer可以读取消息。当然这个例子很简单,在真正的环境中,我们可以利用消息的所有属性甚至是消息的内容作为判断的依据。

  现在这个policy必须配置到broker中。第一步也是最重要的是编译这个class文件并将其打包到JAR文件中。将这个JAR文件放置在ActiveMQ目录的lib文件夹下。第二步在ActiveMQ XML配置文件中生成AuthorizationPolicy类的实例(使用节点<messageAuthorizationPolicy>)。代码如下:

...

<messageAuthorizationPolicy>

<bean

class="org.apache.activemq.book.ch6.AuthorizationPolicy"

xmlns="http://www.springframework.org/schema/beans"/>

</messageAuthorizationPolicy>

...

最后一步是启动ActiveMQ并测试我们的policy。代码如下:

${ACTIVEMQ_HOME}/bin/activemq console\

xbean:src/main/resources/org/apache/activemq/book/ch6/activemq-policy.xml

...

Loading message broker from:

xbean:src/main/resources/org/apache/activemq/book/ch6/activemq-policy.xml

...

22:19:23,532 | INFO | PListStore:

/Users/bsnyder/amq/apache-activemq-5.4.1/data/localhost/tmp_storage

started

22:19:23,692 | INFO | JMX consoles can connect toservice:

jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi

22:19:23,717 | INFO | Using Persistence Adapter:KahaDBPersistenceAdapter

[/Users/bsnyder/amq/apache-activemq-5.4.1/data/localhost/KahaDB]

22:19:23,815 | DEBUG | loading

22:19:23,847 | INFO | ActiveMQ 5.4.1 JMS Message Broker(localhost) is

starting

22:19:23,848 | INFO | For help or more informationplease see:

http://activemq.apache.org/

22:19:23,990 | INFO | Scheduler using directory:

/Users/bsnyder/amq/apache-activemq-5.4.1/data/localhost/scheduler

22:19:24,037 | DEBUG | loading

22:19:24,039 | DEBUG | loading

22:19:24,041 | INFO | JobSchedulerStore:

/Users/bsnyder/amq/apache-activemq-5.4.1/data/localhost/schedulerstarted

22:19:24,081 | INFO | Listening for connections at:tcp://localhost:61616

22:19:24,081 | INFO | Connector openwire Started

22:19:24,083 | INFO | ActiveMQ JMS Message Broker

(localhost, ID:mongoose.local-64256-1289971163870-0:0)started

...

如果你在运行broker的机器上运行第三章的例子,那么和原来的配置文件下的执行结果相同。Producer发送消息:

$ mvn exec:java \

-Dexec.mainClass=org.apache.activemq.book.ch3.portfolio.Publisher\

-Dexec.args="CSCO ORCL"

...

Sending: {price=94.51516220513759, stock=ORCL,offer=94.60967736734271,

up=true} on destination: topic://STOCKS.ORCL

Sending: {price=94.12582896629408, stock=ORCL,offer=94.21995479526036,

up=false} on destination: topic://STOCKS.ORCL

Sending: {price=52.82279394171494, stock=CSCO,offer=52.87561673565665,

up=false} on destination: topic://STOCKS.CSCO

Sending: {price=93.30370880341836, stock=ORCL,offer=93.39701251222176,

up=false} on destination: topic://STOCKS.ORCL

Sending: {price=94.0890269658999, stock=ORCL,offer=94.1831159928658,

up=true} on destination: topic://STOCKS.ORCL

Sending: {price=52.50790406130471, stock=CSCO,offer=52.56041196536601,

up=false} on destination: topic://STOCKS.CSCO

Sending: {price=94.11072880595002, stock=ORCL,offer=94.20483953475596,

up=true} on destination: topic://STOCKS.ORCL

Sending: {price=52.947263764976896, stock=CSCO,offer=53.000211028741866,

up=true} on destination: topic://STOCKS.CSCO

Sending: {price=94.40912590172766, stock=ORCL,offer=94.50353502762938,

up=true} on destination: topic://STOCKS.ORCL

Sending: {price=95.0802935408136, stock=ORCL,offer=95.1753738343544,

up=true} on destination: topic://STOCKS.ORCL

Published '10' of '10' price messages

...

Consumer接收到消息:

$ mvn exec:java \

-Dexec.mainClass=org.apache.activemq.book.ch3.portfolio.Consumer\

-Dexec.args="CSCO ORCL"

...

ORCL 94.52 94.61 up

ORCL 94.13 94.22 down

CSCO 52.82 52.88 down

ORCL 93.30 93.40 down

ORCL 94.09 94.18 up

CSCO 52.51 52.56 down

ORCL 94.11 94.20 up

CSCO 52.95 53.00 up

ORCL 94.41 94.50 up

ORCL 95.08 95.18 up

CSCO 52.90 52.96 down

ORCL 95.62 95.71 up

CSCO 53.32 53.37 up

ORCL 95.45 95.55 down

CSCO 53.59 53.64 up

...

但是在broker的控制台中会打出如下日志记录:

INFO | /127.0.0.1:50930

INFO | Permission to consume granted

INFO | /127.0.0.1:50930

INFO | Permission to consume granted

INFO | /127.0.0.1:50930

INFO | Permission to consume granted

INFO | /127.0.0.1:50930

INFO | Permission to consume granted

INFO | /127.0.0.1:50930

INFO | Permission to consume granted

INFO | /127.0.0.1:50930

INFO |Permission to consume granted

但是如果我们在其他主机中运行上述例子,我们的policy会阻止consumer从broker获取消息。并且在broker控制台中会打出如下日志记录:

INFO | /192.168.10.10:50930

INFO | Permission to consume denied

INFO | /192.168.10.10:50930

INFO | Permission to consume denied

INFO | /192.168.10.10:50930

INFO | Permission to consume denied

INFO | /192.168.10.10:50930

INFO | Permission to consume denied

INFO | /192.168.10.10:50930

INFO | Permission to consume denied

INFO | /192.168.10.10:50930

INFO |Permission to consume denied

上面的例子证明消息级别的安全控制是可以实现的。

  Message-levelauthorization是非常强大的。虽然我们只是写了一个简单的例子,但是你可以实现任何安全协议来满足项目需求。但是我们需要记住的是,message authorization策略是作用在经过broker的所有消息上的,所以我们的安全策略要尽量不影响broker的消息吞吐量。

  对于authorization,ActiveMQ提供了一个特殊的类来增强broker-level 操作。下一个小节我们讨论这个特殊的类。

 

 

6.3      Building a custom security plug-in

到目前为止,我们只是讨论了ActiveMQ内置的安全框架。虽然这些特色已经提供了足够的功能来满足我们的大部分需要,但是我们也可以实现更强大的功能。像之前提到的一样,ActiveMQ插件是非常灵活且充满可能性的。它的灵活性来自于BrokerFilter类。这个类可以拦截大部分broker-level操作,例如:添加consumer、添加producer、提交事物、连接到或取消连接到broker等等。我们可以继承BrokerFilter类并重写其中的方法来增加我们的逻辑。

  虽然ActiveMQ 插件不完全是为了安全来设计的,但是我们可以利用插件以及安全控件来实现安全控制。假如之前介绍的安全特性无法满足你的项目需要,你也可以使用自定义解决方案。考虑到你的需求,有两种方法可供选择:

n  实现JAAS login module:之前我们在例子中已经使用了JAAS,在这个例子中我们可以利用之前的代码,因为JAAS不是本书的主要内容,所以我们也不会更深入的谈论他。

n  实现自定义插件来处理安全特性:ActiveMQ包含灵活的插件管理框架,所以你可以自定义实现任何插件,包括实现鉴权功能。所以如果JAAS模型无法满足需要,自定义实现一个插件也是不错的选择。

  在这一个章节,我们会描述如何编写自己的插件来控制连接到broker的客户端只能来自于特定的IP地址。这个概念不会很复杂,但是可以使你窥探到使用BrokerFilter实现安全控制的方法。

 

6.3.1       Implementing the plug-in


--待续--


个人翻译 仅供学习 转载请说明出处

 

0 0
原创粉丝点击