ActiveMQ 安全认证
章节导读
- 如何使用安全认证
- 如何使用授权
- 如何创建一个定制的安全插件
- 使用基于证书的安全认证
认证就是一个验证某些请求受保护的资源的用户或者实体的完整性的过程.一些常见的认证形式包括纯文本密码,一次性密码设备,智能卡等等.Activemq提供了一些简单的认证和JAAS(java认证和java认证服务),和一个用于自定义安全插件的api.在成功认证之后,就被授权可以访问系统资源了.
1.1 认证
所有在MQ实现的安全概念都是插件的形式实现的.
- 简单认证插件---直接在xml或者properties文件中授权认证信息.
- JAAS认证插件----实现了JAAS API,提供了更强力可定制的认证解决方案.
1.1.1 配置简单认证插件
在代理的xml中直接配置身份认证凭证是最简单的一种方式.配置的xml如下:
<broker ...>
<plugins>
<simpleAuthenticationPlugin>
<users>
<authenticationUser username="admin" password="password" groups="admins,publishers,consumers"/>
<authenticationUser username="publisher" password="password" groups="publishers,consumers"/>
<authenticationUser username="consumer" password="password" groups="consumers"/>
<authenticationUser username="guest" password="password" groups="guests"/>
</users>
</simpleAuthenticationPlugin>
</plugins>
</broker>
代码中的改动就是在创建连接时用带用户名密码的方法.
connection = factory.createConnection(username, password);
使用文本密码验证的安全性没办法保证,除非加上ssl. 要保证安全的情况下JAAS 插件更适合.
1.1.2 配置JAAS插件
JAAS提供可插入式的认证,这意味着Mq会使用同样的认证api.这需要去实现javax.security.auth.spi.LoginModule 接口以及Mq配置文件的改变.
1.修改conf/ login.config配置文件
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";
};
PropertiesLoginModule用于jaas登陆模块,定义user的文件在
users.properties中,定义group的文件在groups.properties中
user.properties
admin=admin
publisher=password
consumer=password
guest=password
group.properties
admins=admin
publishers=admin,publisher
consumers=admin,publisher,consumer
guests=guest
1.2 授权
基于认证,如果需要控制更细粒度的权限,就需要授权.
ActiveMq提供了两种级别的授权:操作级别和消息级别的授权,这两种级别的认证提供更详细的级别控制.
1.2.1 Destination级别的授权
对于Destination有三种类型的用户级别的操作 :读,写,管理.下面的xml展示了如何配置:
<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" />
<authorizationEntry topic="ActiveMQ.Advisory.>" read="admins,publishers,consumers,guests" write="admins,publishers,consumers,guests" admin="admins,publishers,consumers,guests" />
</authorizationEntries>
</authorizationMap>
</map>
</authorizationPlugin>
</plugins>
- admins对所有topic有所有的权限
- 消费者可以消费,生产者可以生产消息在STOCK的目录下
- guests组对于STOCKS.ORCL只有读权限
1.2.1 消息级别的授权
在某些情况下,你可能只想允许访问一个destination中的某些特别的消息.要实现这些,我们先要实现org.apache.activemq.security.MessageAuthorizationPolicy接口.
例子如下:只有地址时tcp://127.0.0.1开头的地址才能消费
public class AuthorizationPolicy implements MessageAuthorizationPolicy {
private static final Log LOG = LogFactory.getLog(AuthorizationPolicy.class);
@Override
public boolean isAllowedToConsume(ConnectionContext context, Message message) {
LOG.info(context.getConnection().getRemoteAddress());
String remoteAddress = context.getConnection().getRemoteAddress();
LOG.info("地址:" + remoteAddress);
if (remoteAddress.startsWith("127.0.0.1")) {
LOG.info("Permission to consume granted");
return true;
} else {
LOG.info("Permission to consume denied");
return false;
}
}
}
这个策略必须被打成jar包放入lib/目录下.可以用maven直接打包
执行mvn clean install
然后找到打包好的jar(ActiveMqLearn-0.0.1-SNAPSHOT.jar)复制到lib目录下,然后在配置文件中加入以下的配置,bean节点的class换成自己的类路径
<messageAuthorizationPolicy>
<bean
class="com.zcf.activemq.authorization.AuthorizationPolicy"
xmlns="http://www.springframework.org/schema/beans" />
</messageAuthorizationPolicy>
运行consumer,就会在控制台出现以下信息
如果把remoteAddress.startsWith("127.0.0.1") 改成remoteAddress.startsWith("tcp://127.0.0.1"),那么消息就会被允许消费.
1.3 建立一个定制的安全性插件
brokerFilter提供拦截代理级别的操作.包括增加消费者和生产者,提交事务,增加移除和其它代理的连接.
1.3.1 实现插件
为了限制(基于IP)到代理的连接.我们可以创建一个类,覆盖BrokerFilter.addConnection().方法.
首先创建一个IP连接器
public class IPAuthenticationBroker extends BrokerFilter {
List<String> allowedIPAddresses;
Pattern pattern = Pattern.compile("^/([0-9\\.]*):(.*)");//Ip的正则表达式
public IPAuthenticationBroker(Broker next, List<String> allowedIPAddresses) {
super(next);
this.allowedIPAddresses = allowedIPAddresses;
}
@Override
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);
}
}
然后创建一个插件安装类,它是用于暴露配置以及安装插件到ActiveMq.
package com.zcf.activemq.security.customerplugin;
import java.util.List;
import org.apache.activemq.broker.Broker;
import org.apache.activemq.broker.BrokerPlugin;
public class IPAuthenticationPlugin implements BrokerPlugin {
List<String> allowedIPAddresses;
@Override
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;
}
}
我们还是需要先把刚才生成的类用maven打成jar包放到lib目录下.
1.3.2 配置插件
<plugins>
<bean xmlns="http://www.springframework.org/schema/beans"
id="ipAuthenticationPlugin"
class="com.zcf.activemq.security.customerplugin.IPAuthenticationPlugin">
<property name="allowedIPAddresses">
<list>
<value>127.0.0.1</value>
</list>
</property>
</bean>
</plugins>
通过运行测试可以发现,除了本地的机器可以运行.其它ip的都会被阻止.
1.4 基于证书的安全认证
truststore是放信任的证书的一个store,truststore和keystore的性质是一样的,都是存放key的一个仓库,区别在于,truststore里存放的是只包含公钥的数字证书,代表了可以信任的证书,而keystore是包含私钥的。
Server需要:KeyStore:保存服务端的私钥;Trust KeyStore:保存客户端的授权证书
Client需要: KeyStore:保存客户端的私钥; Trust KeyStore:保存服务端的授权证书
1.4.1 生成证书和truststore
- 打开cmd命令窗口,cd到%JAVA_HOME%\bin\目录下
- 通过命令 keytool -genkey -alias myproducer -keyalg RSA -keystore myproducer.ks keytool -genkey -alias myconsumer-keyalg RSA -keystore myconsumer.ks生成生产者和消费者的私钥
- 通过命令 keytool -genkey -alias mybroker-keyalg RSA -keystore mybroker.ks 生成代理的私钥
- 通过命令 keytool -export -alias myproducer -keystore myproducer.ks -file myproducer_cert keytool -export -alias ,myconsumer -keystore myconsumer.ks -file myconsumer_cert导出生产者消费者证书
- 通过命令 keytool -export -alias mybroker -keystore mybroker.ks -file mybroker_cert生成代理的证书
- 通过命令 keytool -import -alias myproducer -keystore mybroker.ts -file myproducer_cert,keytool -import -alias myconsumer -keystore mybroker.ts -file myconsumer_cert把生产者和消费者的证书加入代理的truststore中去
- 通过命令 keytool -import -alias mybroker -keystore myclient.ts -file mybroker_cert把代理的证书加入客户端信任库中
把mybroker.ks和mybroker.ts放入/conf/文件夹下
把myclient.ts和myconsumer.ks,myproducer.ks放入项目中,具体位置如下
1.4.2 配置代理
修改activemq.xml文件,
<sslContext>
<sslContext keyStore="file:${activemq.base}/conf/mybroker.ks"
keyStorePassword="XXX" trustStore="file:${activemq.base}/conf/mybroker.ts" trustStorePassword="XXX"/>
</sslContext>
<transportConnectors>
<transportConnector name="ssl"
uri="ssl://localhost:61617?needClientAuth=true" />
</transportConnectors>
在这里先配置了ssl的链接,needClientAuth参数代表需要在客户端连接的时候检查证书是否在信任库中.
sslContext中配置了代理私钥的证书路径以及密码,信任库的路径以及密码
生产者代码:
package com.zcf.activemq.security.cert;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import javax.jms.Connection;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageProducer;
import javax.jms.ObjectMessage;
import javax.jms.Session;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import org.apache.activemq.ActiveMQSslConnectionFactory;
public class Publisher {
private static String brokerURL = "ssl://localhost:61617";
private static transient ActiveMQSslConnectionFactory factory;
private transient Connection connection;
private transient Session session;
private transient MessageProducer producer;
private static int count = 10;
private static int total;
private static int id = 1000000;
private String jobs[] = new String[] { "suspend", "delete" };
public Publisher() throws JMSException, Exception, NoSuchAlgorithmException, KeyStoreException, CertificateException, GeneralSecurityException, IOException {
factory = new ActiveMQSslConnectionFactory(brokerURL);
factory.setKeyAndTrustManagers(getKeyManagers("myproducer.ks", "密码"),
getTrustManagers("myclient.ts"),
new java.security.SecureRandom());
connection = factory.createConnection();
connection.start();
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
producer = session.createProducer(null);
}
public void close() throws JMSException {
if (connection != null) {
connection.close();
}
}
public static void main(String[] args) throws NoSuchAlgorithmException, KeyStoreException, Exception {
Publisher publisher = new Publisher();
while (total < 1) {
for (int i = 0; i < count; i++) {
publisher.sendMessage();
}
total += count;
System.out.println("Published '" + count + "' of '" + total + "' job messages");
try {
Thread.sleep(1000);
} catch (InterruptedException x) {
}
}
publisher.close();
}
public void sendMessage() throws JMSException {
int idx = 0;
while (true) {
idx = (int) Math.round(jobs.length * Math.random());
if (idx < jobs.length) {
break;
}
}
String job = jobs[idx];
Destination destination = session.createTopic("STOCKS." + job);
Message message = session.createObjectMessage(id++);
System.out.println("Sending: id: " + ((ObjectMessage) message).getObject() + " on queue: " + destination);
producer.send(destination, message);
}
private KeyManager[] getKeyManagers(String keyStore, String keyStorePassword)
throws java.security.NoSuchAlgorithmException, java.security.KeyStoreException,
java.security.GeneralSecurityException, java.security.cert.CertificateException, java.io.IOException,
java.security.UnrecoverableKeyException {
System.out.println("Initiating KeyManagers");
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(ClassLoader.getSystemResourceAsStream(keyStore), keyStorePassword.toCharArray());
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(ks, keyStorePassword.toCharArray());
System.out.println("Initiated KeyManagers");
return kmf.getKeyManagers();
}
private TrustManager[] getTrustManagers(String trustStore) throws java.security.NoSuchAlgorithmException,
java.security.KeyStoreException, java.io.IOException, java.security.GeneralSecurityException {
System.out.println("Initiating TrustManagers");
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(ClassLoader.getSystemResourceAsStream(trustStore), null);
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(ks);
System.out.println("Initiated TrustManagers");
return tmf.getTrustManagers();
}
}
消费者代码:
package com.zcf.activemq.security.cert;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import javax.jms.Connection;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.ObjectMessage;
import javax.jms.Session;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import org.apache.activemq.ActiveMQSslConnectionFactory;
import org.apache.log4j.Logger;
public class Consumer {
private static Logger logger = Logger.getLogger(Consumer.class);
private static String brokerURL = "ssl://localhost:61617";
private static transient ActiveMQSslConnectionFactory factory;
private transient Connection connection;
private transient Session session;
private String jobs[] = new String[] { "suspend", "delete" };
public Consumer() throws JMSException, UnrecoverableKeyException, NoSuchAlgorithmException, KeyStoreException, CertificateException, GeneralSecurityException, IOException {
factory = new ActiveMQSslConnectionFactory(brokerURL);
factory.setKeyAndTrustManagers(getKeyManagers("myconsumer.ks", "8797393"),
getTrustManagers("myclient.ts"),
new java.security.SecureRandom());
connection = factory.createConnection();
connection.start();
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
}
public void close() throws JMSException {
if (connection != null) {
connection.close();
}
}
public static void main(String[] args) throws JMSException, InterruptedException, UnrecoverableKeyException, NoSuchAlgorithmException, KeyStoreException, CertificateException, GeneralSecurityException, IOException {
Consumer consumer = new Consumer();
for (String job : consumer.jobs) {
Destination destination = consumer.getSession().createTopic("STOCKS." + job);
MessageConsumer messageConsumer = consumer.getSession().createConsumer(destination);
messageConsumer.setMessageListener(new MessageListener() {
public void onMessage(Message message) {
try {
//do something here
System.out.println( ((ObjectMessage)message).getObject());
logger.info(((ObjectMessage)message).getObject());
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}
public Session getSession() {
return session;
}
private KeyManager[] getKeyManagers(String keyStore, String keyStorePassword)
throws java.security.NoSuchAlgorithmException, java.security.KeyStoreException,
java.security.GeneralSecurityException, java.security.cert.CertificateException, java.io.IOException,
java.security.UnrecoverableKeyException {
System.out.println("Initiating KeyManagers");
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(ClassLoader.getSystemResourceAsStream(keyStore), keyStorePassword.toCharArray());
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(ks, keyStorePassword.toCharArray());
System.out.println("Initiated KeyManagers");
return kmf.getKeyManagers();
}
private TrustManager[] getTrustManagers(String trustStore) throws java.security.NoSuchAlgorithmException,
java.security.KeyStoreException, java.io.IOException, java.security.GeneralSecurityException {
System.out.println("Initiating TrustManagers");
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(ClassLoader.getSystemResourceAsStream(trustStore), null);
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(ks);
System.out.println("Initiated TrustManagers");
return tmf.getTrustManagers();
}
}
1.4.3 基于证书的授权配置
在上面的activemq.xml的基础上加上下面的XML
<plugins>
<jaasCertificateAuthenticationPlugin configuration="activemq-certificate" />
<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" />
<authorizationEntry topic="ActiveMQ.Advisory.>" read="admins,publishers,consumers,guests" write="admins,publishers,consumers,guests" admin="admins,publishers,consumers,guests" />
</authorizationEntries>
</authorizationMap>
</map>
</authorizationPlugin>
</plugins>
login.config文件修改成,activemq-certificate对应jaasCertificateAuthenticationPlugin节点中的 configuration属性
activemq-certificate {
org.apache.activemq.jaas.TextFileCertificateLoginModule
required debug=true
org.apache.activemq.jaas.textfiledn.user="users.properties"
org.apache.activemq.jaas.textfiledn.group="groups.properties";
};
users.proerties修改成
admin=admin
publisher=password
consumer=password
guest=password
sslconsumer=CN=MYCONSUMER, OU=HYT, O=HUIYUNTONG, L=FZ, ST=FJ, C=CN
sslpublisher=CN=MYPRODUCER, OU=HYT, O=HUIYUNTONG, L=FZ, ST=FJ, C=CN
sslconsumer,sslconsumer用户后面对应的密码属性都是生成生产者消费者过程中填写的信息(属性之间逗号之后要有空隔)
groups.proerties修改成
admins=admin
publishers=admin,publisher,sslpublisher
consumers=admin,publisher,consumer,sslconsumer
guests=guest
这样就可以控制更细粒度的权限了.
- 大小: 25.2 KB
- 大小: 28.3 KB
- 大小: 27.1 KB
分享到:
相关推荐
理解并正确配置SSL双向认证对于确保在ActiveMQ上的通信安全至关重要。由于这是一个涉及到多个步骤的过程,建议在每个环节都仔细检查,确保所有证书和配置都正确无误。如果在实施过程中遇到困难,不要犹豫寻求帮助,...
10. **安全配置**:理解ActiveMQ的安全模型,包括用户身份验证和权限控制,这对于企业级部署至关重要。 总之,这个"activeMQ收发工具.jar"是调试和测试ActiveMQ服务器的强大辅助工具,通过它,开发者可以深入理解...
9. **安全性**:ActiveMQ支持基于角色的访问控制(RBAC)、SSL加密以及JAAS认证,保障了消息传递的安全性。 10. **性能优化**:ActiveMQ提供多种性能优化策略,例如预取(prefetching)技术,允许消费者在需要时...
以上步骤完成了ActiveMQ的基本安装、配置以及安全认证设置。需要注意的是,实际部署时还需要根据具体需求进一步调整配置文件,如调整监听端口、增加额外的安全策略等。此外,为了确保系统的稳定性和安全性,建议定期...
理解ActiveMQ的配置文件对于优化其性能、确保稳定性和安全性至关重要。 ActiveMQ的配置主要通过`activemq.xml`文件进行,这个文件位于ActiveMQ安装目录的`conf`文件夹下。这个XML文件定义了ActiveMQ服务器的核心...
7. **安全机制**:ActiveMQ支持多种安全认证和授权机制,如JAAS(Java Authentication and Authorization Service),可以保护消息的安全传输。 8. **QoS(Quality of Service)策略**:提供不同的服务质量级别,如...
5. 安全性:ActiveMQ内置了用户认证和授权机制,可以通过SSL/TLS加密传输,保障数据的安全性。 二、ActiveMQ应用场景 1. 微服务通信:在微服务架构中,ActiveMQ作为服务间通信的桥梁,实现异步解耦和数据同步。 2. ...
连接器用于定义客户端如何连接到ActiveMQ服务器,包括网络配置、安全认证等;消息持久化策略决定了消息是否需要存储在磁盘上,这对于保证消息不丢失至关重要;安全性配置则涉及到用户认证、权限控制等内容,确保只有...
- **安全性**:ActiveMQ提供基于用户认证和授权的安全管理,确保消息传输的安全。 - **管理工具**:内置的Web控制台允许用户监控和管理消息代理,方便调试和故障排查。 3. **配置与使用** - **安装与启动**:...
### ActiveMQ-CPP 开发手册知识点详述 #### 一、引言 - **编写目的**:本手册旨在帮助开发者快速掌握 CMS (C++ Messaging Service) 的使用方法,提高 C++ 开发者在消息传递系统方面的开发效率,并作为 CMS 开发的...
7. **安全控制**:ActiveMQ 提供了基于角色的访问控制(Role-Based Access Control, RBAC),可以对用户和资源进行精细的权限管理。 **ActiveMQ 使用场景** 1. **解耦组件**:在大型系统中,通过 ActiveMQ 实现...
7. **安全控制**:ActiveMQ提供基于角色的访问控制(RBAC)和SSL/TLS加密,确保了消息传输的安全性。 8. **管理与监控**:ActiveMQ提供了Web管理控制台和JMX(Java Management Extensions)接口,用户可以轻松监控...
ActiveMQ还支持多种安全机制,如Kerberos认证、LDAP集成、SSL加密连接等高级功能,这些功能可以在其官方网站上找到详细的配置指南和说明。在实际应用中,应根据实际安全需求选择合适的安全机制进行配置。 以上便是...
7. **管理工具**:ActiveMQ自带了一个Web控制台,方便管理员监控和管理消息代理,查看消息队列状态、消费者信息、日志等。 8. **持久化机制**:ActiveMQ支持多种持久化机制,包括本地文件系统、LevelDB、JDBC数据库...
为了提高安全性,通常需要对ActiveMQ进行安全配置,防止未经授权的用户访问。 ##### 1. 用户认证配置 在`conf/activemq.xml`文件中添加简单的认证插件配置: ```xml ,admins"/> ``` 这里定义了一个名...
6. **安全性和认证**:如果ActiveMQ服务器配置了SSL/TLS加密或需要用户名/密码认证,客户端也需要相应地设置安全连接和身份验证。 7. **调试和测试**:在实际部署前,要进行充分的单元测试和集成测试,确保MQTT...
7. **安全配置** 为了防止未经授权的访问,ActiveMQ提供了多种安全策略。这里以最简单的授权配置为例,需要编辑`conf/activemq.xml`文件,在broker标签中添加认证用户信息。例如,创建一个名为`xiaoxg`的用户,密码...
你可以在“conf”目录下的“users.properties”和“groups.properties”文件中定义用户和权限,而在“activemq.xml”中配置相应的安全策略。 客户端可以通过多种方式与ActiveMQ MQTT服务器交互。例如,可以使用MQTT...