您的位置:首页 > 其它

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

2017-03-10 16:19 281 查看
场景--由于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);   

         
4000
  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文件请从下载页面下载
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息