azkaban定制用户管理(azkaban Custom User Manager)

来源:互联网 发布:java学生选课系统源码 编辑:程序博客网 时间:2024/05/16 07:51

场景--由于azkaban管理用户是通过配置xml来实现的,不太符合我司需求,所以写了一个从mysql数据库读取用户的插件替换azkaban默认的用户管理,但是目前只是实现了从数据库读取数据,想要新增用户的话只能按照表的格式导入到数据库,这里主要说的是思路,只贴出关键部分的代码,源码,编译后的jar包,以及sql文件我会上传到下载目录下供用户下载


azkaban的安装参考 azkaban3.12 编译与安装 - shp5174的博客 - 博客频道 - CSDN.NET

导入jar包

因为azkaban的用户手册上说明定制用户需要实现 UserManager接口所以创建一个java工程 

并导入azkaban-common.xxx.jar包,UserManager接口在这个jar包中,再导入一些必要的jar包,如图



创建util连接数据库

懂java的应该都看的懂,就是平时用java连接数据库的方式,所以这里只简单说一下

先创建一个property文件,用来保存连接参数,


内容如下

url = jdbc:mysql://10.80.2.7/azkaban
name = com.mysql.jdbc.Driver
user = azkaban
password = azkaban

创建jdbc类用来读取这份配置文件

关键部分代码如下

  /**  
     * 私有构造方法,不需要创建对象  
     */   
    private Jdbc() {   
    Properties prop = new Properties();   
        InputStream in = Object.class.getResourceAsStream("/resource/jdbc.properties");   
        try {   
            prop.load(in);   
            url = prop.getProperty("url").trim();   
            name = prop.getProperty("name").trim();   
            user = prop.getProperty("user").trim(); 
            password = prop.getProperty("password").trim(); 
        } catch (IOException e) {   
            e.printStackTrace();   
        }  
    }   
    
    private static final Jdbc jdbc = new Jdbc();  


    // 静态方法返回该类的实例
    public static Jdbc getInstance() {  
        return jdbc;  
    } 

创建JdbcFactory类来真正连接数据库

关键部分代码如下

private JdbcFactory() {
    Jdbc jdbc=Jdbc.getInstance();
    url=jdbc.getUrl();
    name=jdbc.getName();
    user=jdbc.getUser();
    password=jdbc.getPassword();
    try {  
Class.forName(name);//指定连接类型  
conn = DriverManager.getConnection(url, user, password);//获取连接  
} catch (Exception e) {  
e.printStackTrace();  
}  
    }

另外还针对我的设计,写了一个定制的查询数据库语句,之所以是定制,是因为这个方法并不能通用,只符合我目前的需求

public void getConnection() {  
    if(conn ==null) {
    try {  
    Class.forName(name);//指定连接类型  
    conn = DriverManager.getConnection(url, user, password);//获取连接  
    } catch (Exception e) {  
    e.printStackTrace();  
    }  
    }
    } 

public List<String> find(String sql,String... list)  {
    this.getConnection();
    List<String> resultList=new ArrayList<String>();
    try {  
    pst = conn.prepareStatement(sql);//准备执行语句  
    //设置参数
    for(int i=0;i<list.length;i++) {
    pst.setString(i+1, list[i]);
    }
    String s=pst.toString();
    System.out.println("==========sql:"+s.substring(s.indexOf("SELECT")));
    ResultSet rs=pst.executeQuery();
             while (rs.next()) {  
            resultList.add(rs.getString(1));
             }
             rs.close();  
//             this.close();
         } catch (SQLException e) {  
             e.printStackTrace();  
         }  
    return resultList;
    }

util的准备到此结束

数据库表的设计

DROP TABLE IF EXISTS `group`;
CREATE TABLE `group` (
  `name` varchar(255) NOT NULL,
  `create_time` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`name`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC;


-- ----------------------------
-- Records of group
-- ----------------------------
INSERT INTO `group` VALUES ('admin', null);
INSERT INTO `group` VALUES ('azkaban', null);
INSERT INTO `group` VALUES ('test1', null);


-- ----------------------------
-- Table structure for `group_role`
-- ----------------------------
DROP TABLE IF EXISTS `group_role`;
CREATE TABLE `group_role` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `group_name` varchar(255) DEFAULT NULL,
  `role_name` varchar(255) DEFAULT NULL,
  `create_time` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=5 DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC;


-- ----------------------------
-- Records of group_role
-- ----------------------------
INSERT INTO `group_role` VALUES ('3', 'admin', 'admin', null);


-- ----------------------------
-- Table structure for `role`
-- ----------------------------
DROP TABLE IF EXISTS `role`;
CREATE TABLE `role` (
  `name` varchar(255) NOT NULL,
  `create_time` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`name`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC;


-- ----------------------------
-- Records of role
-- ----------------------------
INSERT INTO `role` VALUES ('admin', null);
INSERT INTO `role` VALUES ('azkaban', null);
INSERT INTO `role` VALUES ('test1', null);


-- ----------------------------
-- Table structure for `role_permission`
-- ----------------------------
DROP TABLE IF EXISTS `role_permission`;
CREATE TABLE `role_permission` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `role_name` varchar(255) DEFAULT NULL,
  `permission` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=6 DEFAULT CHARSET=latin1;


-- ----------------------------
-- Records of role_permission
-- ----------------------------
INSERT INTO `role_permission` VALUES ('1', 'admin', 'ADMIN');
INSERT INTO `role_permission` VALUES ('2', 'azkaban', 'ADMIN');
INSERT INTO `role_permission` VALUES ('4', 'test1', 'WRITE');


-- ----------------------------
-- Table structure for `user`
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
  `name` varchar(255) NOT NULL,
  `password` varchar(255) NOT NULL,
  `email` varchar(255) DEFAULT NULL,
  `create_time` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`name`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;


-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES ('azkaban', 'azkaban', null, null);
INSERT INTO `user` VALUES ('admin', 'admin', null, null);
INSERT INTO `user` VALUES ('test1', 'test1', null, null);


-- ----------------------------
-- Table structure for `user_group`
-- ----------------------------
DROP TABLE IF EXISTS `user_group`;
CREATE TABLE `user_group` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `group_name` varchar(255) DEFAULT NULL,
  `user_name` varchar(255) DEFAULT NULL,
  `create_time` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=4 DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC;


-- ----------------------------
-- Records of user_group
-- ----------------------------
INSERT INTO `user_group` VALUES ('3', 'admin', 'admin', null);


-- ----------------------------
-- Table structure for `user_role`
-- ----------------------------
DROP TABLE IF EXISTS `user_role`;
CREATE TABLE `user_role` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_name` varchar(255) DEFAULT NULL,
  `role_name` varchar(255) DEFAULT NULL,
  `create_time` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=4 DEFAULT CHARSET=latin1;


-- ----------------------------
-- Records of user_role
-- ----------------------------
INSERT INTO `user_role` VALUES ('1', 'admin', 'admin', null);
INSERT INTO `user_role` VALUES ('2', 'azkaban', 'azkaban', null);
INSERT INTO `user_role` VALUES ('3', 'test1', 'test1', null);


有些表可能在逻辑里并没有用到,懒得修改了.


实现UserManager接口


其中需要实现的只有getRole,getUser两个方法,其他的默认返回就行了

首先说说getUser方法

这个方法要做的事是,传入用户名和密码,返回一个user对象,这个user对象包属性如下:

private final String userid;
  private String email = "";
  private Set<String> roles = new HashSet<String>();
  private Set<String> groups = new HashSet<String>();
  private UserPermissions userPermissions;

可以看出这个用户的角色和群组都用用set保存起来了

所以我在getUser方法中是这么写的

public User getUser(String userName, String password) throws UserManagerException {

if (userName == null || userName.trim().isEmpty()) {
     throw new UserManagerException("请输入账号");
   } else if (password == null || password.trim().isEmpty()) {
    throw new UserManagerException("请输入密码");
   }
   
//查询用户名和密码是否正确
String existSql ="SELECT name FROM user u where u.name=? and u.`password`=?";
if(jf.find(existSql, userName,password).size()==0) {
throw new UserManagerException("账号密码错误或不存在");
}
User user = new User(userName);
//查询用户拥有的group
String findRoleSql="SELECT group_name FROM user_group ug  where ug.user_name=?";
List<String> groups=jf.find(findRoleSql, userName);
//用户可能没有group,因为在设置的时候可以直接为用户指定角色,而跳过group这一步
if(groups.size()>0) {
for(String group:groups) {
user.addGroup(group);
}
}
//同理查询用户角色,并保存到到 role中,用户的角色来源分为两部分一种是group下的角色组,一种是用户直接分配的角色
String findperMissionSql="SELECT gr.role_name from user_group ug,group_role gr " 
+"where ug.user_name=? and ug.group_name=gr.group_name union "
+"select ur.role_name from user_role ur where ur.user_name=?";
List<String> roles=jf.find(findperMissionSql, userName,userName);
if(roles.size()>0) {
for(String role:roles) {
user.addRole(role);
}
}
return user;
}

再来看 getRole方法,这个方法要做的事是传入一个角色名,返回一个包含该角色拥有的权限的角色类

Role类的属性如下

 private final String name;
  private final Permission globalPermission;

getRole方法的实现如下:

public Role getRole(String roleName) {
String findRoleSql="SELECT rp.permission FROM role_permission rp  where rp.role_name=?";
List<String> permissions=jf.find(findRoleSql, roleName);
Role role=null;
if(permissions.size()>0) {
Permission perm = new Permission();
for (String permString : permissions) {
try {
Permission.Type type = Permission.Type.valueOf(permString);
perm.addPermission(type);
} catch (IllegalArgumentException e) {
logger.error("Error adding type " + permString
+ ". Permission doesn't exist.", e);
}
}
role = new Role(roleName, perm);
}
return role;
}


到目前,功能代码实现完了,但是由于我忽略了官方文档的一句话,所以导致调试了很久都运行不了;

The constructor should take an azkaban.utils.Props object. The contents of azkaban.properties will be available for the UserManager for configuration.

定制的用户管理类必须要有一个参数为Props的构造方法,这个构造方法用来获取azkaban.properties文件的路径.

public MyUserManager(Props props) {
   xmlPath = props.getString(XML_FILE_PARAM);
}

把几个类打成jar包,丢到extlib文件夹中


jar包不需要添加到这次打包的jar包中,因为这些包之前就存在的.



修改azkaban.properties中的用户管理默认类


user.MyUserManager是class文件的路径

最后重启azkaban就可以了


原谅我一点私心:源码,jar包以及sql文件请从下载页面下载

0 0
原创粉丝点击