activemq自定义安全验证插件,集成mysql

一.下载插件代码所需jar包,我是在maven中引入,然后再copy到activemq的指定目录:

    
        
        
            org.apache.activemq
            activemq-broker
            5.15.8
        
        
        
            org.apache.activemq
            activemq-jaas
            5.15.8
        
        
        
            mysql
            mysql-connector-java
            5.1.47
        

        
        
            org.springframework
            spring-jdbc
            4.3.18.RELEASE
        
    

将mysql-connector-java-5.1.47.jar包copy到C:\apache-activemq-5.15.8\lib目录下,将spring-jdbc-4.3.18.RELEASE.jar包copy到C:\apache-activemq-5.15.8\lib\optional目录下。注意:1.spring-jdbc版本要和C:\apache-activemq-5.15.8\lib\optional目录下的spring版本相同。2.mysql版本建议5.1.47,因为6.0+版本的连接驱动包有所改变,不是com.mysql.jdbc.Driver。

二.编辑C:\apache-activemq-5.15.8\conf下的activemq.xml,节点配置改为:


    
        
			
                file:${activemq.conf}/credentials.properties
                file:${activemq.conf}/db.properties
                  
        		
    

   
    
    

	  
      
              
              
              
              
      
    
    
        
            
        
    

然后在节点中的最后添加配置:

		
            						
                
                    
                
            
        

		
    

其中db.properties是自己新建的配置文件,内容如下:

jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/yzh?autoReconnect=true&useUnicode=true&characterEncoding=utf8&useSSL=false
jdbc.username=root
jdbc.password=123456

创建好后copy到C:\apache-activemq-5.15.8\conf目录下。

这样服务端的配置就完成了,下面是自定义插件的代码。

三.认证插件的编码:

package my.plugin;

import org.apache.activemq.broker.Broker;
import org.apache.activemq.broker.BrokerPlugin;
import org.springframework.jdbc.core.JdbcTemplate;

import java.util.List;

/**
 * description:
 * author: 
 * date: 2018-12-07 09:54
 **/
public class MyAuthenticationPlugin implements BrokerPlugin {

    JdbcTemplate jdbcTemplate;//注入JdbcTemplate

    public MyAuthenticationPlugin(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    public Broker installPlugin(Broker broker) throws Exception {
        return new MyAuthenticationBroker(broker,jdbcTemplate);
    }

}

其中MyAuthenticationBroker的编码:

package my.plugin;

import org.apache.activemq.broker.Broker;
import org.apache.activemq.broker.ConnectionContext;
import org.apache.activemq.command.ConnectionInfo;
import org.apache.activemq.security.AbstractAuthenticationBroker;
import org.apache.activemq.security.SecurityContext;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.apache.activemq.jaas.GroupPrincipal;

import java.security.Principal;
import java.security.cert.X509Certificate;
import java.util.*;

/**
 * description:  broker的实现,附带方法过滤
 * author: yangzihe
 * date: 2018-12-07 09:50
 **/
public class MyAuthenticationBroker extends AbstractAuthenticationBroker {

    private JdbcTemplate jdbcTemplate;

    public MyAuthenticationBroker(Broker next, JdbcTemplate jdbcTemplate) {
        super(next);
        this.jdbcTemplate = jdbcTemplate;
    }

    /**
     * 创建连接的时候拦截
     *
     * @param context
     * @param info
     * @throws Exception
     */
    @Override
    public void addConnection(ConnectionContext context, ConnectionInfo info) throws Exception {
        SecurityContext securityContext = context.getSecurityContext();
        if (securityContext == null) {
            System.out.println("=======securityContext=" + securityContext);
            System.out.println("=======username=" + info.getUserName() + ",password=" + info.getPassword());
            securityContext = authenticate(info.getUserName(), info.getPassword(), null);
            System.out.println("=======auth end,securityContext=" + securityContext);
            context.setSecurityContext(securityContext);
            securityContexts.add(securityContext);
        }

        try {
            super.addConnection(context, info);
        } catch (Exception e) {
            securityContexts.remove(securityContext);
            context.setSecurityContext(null);
            throw e;
        }
    }

    /**
     * 查询数据库获取user
     *
     * @param username
     * @return
     */
    private User getUser(String username) {
        String sql = "select * from db_user where user_name=? limit 1";
        try {
            User user = jdbcTemplate.queryForObject(sql, new Object[]{username}, new BeanPropertyRowMapper(User.class));
            System.out.println("===========mysql user = " + user);
            return user;
        } catch (EmptyResultDataAccessException e) {
            return null;
        }
    }

//    public static Map map = null;
//
//    public void getAllUser() {
//        String sql = "select * from db_user";
//        List list = jdbcTemplate.query(sql, new BeanPropertyRowMapper(User.class));
//        map = new LinkedHashMap();
//        for (User user : list) {
//            System.err.println(user);//debug
//            map.put(user.getUser_name(), user);
//        }
//    }

    /**
     * 认证
     *
     * @param username
     * @param password
     * @param peerCertificates
     * @return
     * @throws SecurityException
     */
    public SecurityContext authenticate(String username, String password, X509Certificate[] peerCertificates) throws SecurityException {
        SecurityContext securityContext = null;
        User user = getUser(username);
        //验证用户信息
        if (user != null && user.getPass_word().equals(password)) {
            securityContext = new SecurityContext(username) {
                @Override
                public Set getPrincipals() {
                    Set groups = new HashSet();
                    groups.add(new GroupPrincipal("users"));//默认加入了users的组
                    return groups;
                }
            };
        } else {
            throw new SecurityException("my auth plugin authenticate failed");
        }
        return securityContext;
    }
}

其中User是数据库表db_user的映射实体类:

package my.plugin;

/**
 * description:
 * author: yangzihe
 * date: 2018-12-07 16:25
 **/
public class User {

    private String user_name;

    private String pass_word;

    @Override
    public String toString() {
        return "User{" +
                "user_name='" + user_name + '\'' +
                ", pass_word='" + pass_word + '\'' +
                '}';
    }

    public User() {
    }

    public User(String user_name, String pass_word) {
        this.user_name = user_name;
        this.pass_word = pass_word;
    }

    public String getUser_name() {
        return user_name;
    }

    public void setUser_name(String user_name) {
        this.user_name = user_name;
    }

    public String getPass_word() {
        return pass_word;
    }

    public void setPass_word(String pass_word) {
        this.pass_word = pass_word;
    }
}

最后,数据库表的sql:

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for db_user
-- ----------------------------
DROP TABLE IF EXISTS `db_user`;
CREATE TABLE `db_user`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,
  `pass_word` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of db_user
-- ----------------------------
INSERT INTO `db_user` VALUES (1, 'admin', 'admin');

SET FOREIGN_KEY_CHECKS = 1;

四.activemq broker服务端配置修改和插件代码的编写都已完成,最后就是启动activemq,cmd进入C:\apache-activemq-5.15.8\bin,执行activemq start,或者直接找对应的64位的activemq.bat执行文件双击。服务启动后,客户端再次连接的时候,username=admin password=admin,如果不是将连接失败。(在插件代码中可自定义自己的验证逻辑)

你可能感兴趣的:(activemq)