Сегодня мы рассмотрим защиту брокера ActiveMQ с помощью Java и SQL, написав наш собственный плагин для ActiveMQ.
Вы также можете обратиться к официальной документации ActiveMQ, которая объясняет, как вы можете написать свои собственные плагины для ActiveMQ здесь и здесь .
Мы создадим простое приложение на Java, которое будет перехватывать всех клиентов, которые пытаются подключиться к нашему брокеру, и на основе clientID мы будем искать имя пользователя и пароль для клиента, пытающегося подключиться к нашему брокеру. Если имя пользователя и пароль совпадают с предварительно настроенными именем пользователя и паролем и ClientID, мы разрешим клиенту подключиться к нашему брокеру, иначе мы выдадим исключение безопасности.
Основная концепция того, что мы разрабатываем, заключается в следующем:
- Гибкость API плагинов ActiveMQ проистекает из
BrokerFilter
класса BrokerFilter
Класс предоставляет возможность перехватывать многие из доступных операций брокера на уровне- Вы должны расширить
BrokerFilter
класс и переопределить его методы в соответствии с вашими потребностями. (Мы собираемся переопределитьaddConnection
метод, который запускается, когда клиент пытается подключиться к брокеру). - Вы должны реализовать
BrokerPlugin
класс и переопределить егоinstallPlugin
метод, чтобы создать экземпляр плагина и вернуть нового перехваченного посредника.
Это означает, что мы должны создать два класса:
1) Класс, отвечающий за установку плагина.
2) Класс, который будет содержать логику аутентификации.
Давайте запачкаем руки частью кода.
Создайте новый проект Java (предпочтительно проект Maven) и добавьте зависимости для брокера active-mq и соединителя SQL:
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-broker</artifactId>
<version>5.15.8</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.15</version>
</dependency>
Мы создадим класс как реализацию класса , как показано ниже Installer
BrokerPlugin
package com.authplugin.deviceauth;
import java.sql.Connection;
import java.sql.DriverManager;
import org.apache.activemq.broker.Broker;
import org.apache.activemq.broker.BrokerPlugin;
public class MyAuthPlugin implements BrokerPlugin {
public String url;
public String username;
public String password;
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
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;
}
public Broker installPlugin(Broker broker) throws Exception {
Class.forName("com.mysql.cj.jdbc.Driver");
Connection con = DriverManager.getConnection(this.url, this.username, this.password);
return new MyAuthBroker(broker, con);
}
}
Здесь мы предоставили необходимые свойства для работы нашего плагина.
Поскольку плагин будет инициализирован аналогично Spring Bean в XML, мы можем указать значения для таких свойств, как URL источника данных, имя пользователя и пароль в файле XML, в который мы собираемся поместить наш плагин.
Затем мы должны создать класс фильтра путем расширения и, поскольку мы собираемся фильтровать соединения с нашим брокером, мы будем переопределять метод, как показано ниже: BrokerFilter,
addConnection
package com.authplugin.deviceauth;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.apache.activemq.broker.Broker;
import org.apache.activemq.broker.BrokerFilter;
import org.apache.activemq.broker.ConnectionContext;
import org.apache.activemq.command.ConnectionInfo;
public class MyAuthBroker extends BrokerFilter {
PreparedStatement pstmt;
public MyAuthBroker(Broker next,Connection con) {
super(next);
try {
pstmt = con.prepareStatement("select * from devices where clientID= ?");
} catch (SQLException e) {
e.printStackTrace();
}
}
public void addConnection(ConnectionContext context, ConnectionInfo info) throws Exception {
try {
pstmt.setString(1, info.getClientId());
ResultSet rs = pstmt.executeQuery();
if (rs.next()) {
String clientID = rs.getString("clientID");
String username = rs.getString("username");
String password = rs.getString("password");
if (username.equals(info.getUserName()) && password.equals(info.getPassword())) {
super.addConnection(context, info);
} else {
// username or password does not match
throw new SecurityException("invalid username or password from deviceID : " + clientID);
}
} else {
// device id not in DB, throw exception
throw new SecurityException("Client ID not in DB : " + info.getClientId());
}
} catch (SecurityException e) {
System.out.println(e.getMessage());
throw new Exception();
}
}
}
После этого нам нужно создать в базе данных таблицу устройств, в которой можно хранить имя пользователя и пароль для различных клиентов (в моем случае это устройства), по крайней мере, с тремя столбцами — clientID, username и password.
Скомпилируйте этот проект, чтобы создать jar, который мы поместили бы в брокер (deviceauth-0.0.1-SNAPSHOT.jar)
Теперь нам просто нужно разместить плагин в папке lib каталога установки брокера ActiveMQ вместе с jar-коннектором SQL. Не забудьте также поместить соединитель SQL в папку lib.
Поместив плагин и
jar-файлы коннектора в папку lib, перейдите в {activemq-installation-directory} /conf/activemq.xml и поместите следующие строки между тегом посредника с соответствующими свойствами соединения с базой данных. Кроме того, если вы назвали класс чем-то отличным от того, который указан в приведенном ниже теге bean, вы должны обновить его тоже:
<broker xmlns="http://activemq.apache.org/schema/core" brokerName="localhost" dataDirectory="${activemq.data}">
.
.
.
<plugins>
<bean id="authPlugin" class="com.authplugin.deviceauth.MyAuthPlugin" xmlns="http://www.springframework.org/schema/beans">
<property name="url">
<value>{your-db-URL-here}</value>
</property>
<property name="username">
<value>{your-db-username-here}</value>
</property>
<property name="password">
<value>{your-db-password-here}</value>
</property>
</bean>
</plugins>
.
</broker>
Это оно! Запустите посредник, и теперь только клиенты с именем пользователя и паролем, назначенными им в базе данных, в соответствии с clientID, могут подключаться к посреднику.
Полный код для плагина доступен на моем GitHub здесь .
Я надеюсь, что этот пост был полезным и что вы узнали что-то новое сегодня. Спасибо за чтение и счастливого кодирования!