项目中加入activiti后,用户权限管理处理的三种方式

同步或者重构Activiti Identify用户数据的多种方案比较

相信每个涉及到用户的系统都有一套用户权限管理平台或者模块,用来维护用户以及在系统内的功能、数据权限,我们使用的Activiti工作流引擎配套设计了包括User、Group的Identify模块,怎么和业务数据同步呢,这个问题是每个新人必问的问题之一,下面介绍几种同步方案,最后总结比较。

方案一:调用IdentifyService接口完成同步

参考IdentifyService接口Javadoc:http://www.activiti.org/javadocs/org/activiti/engine/IdentityService.html

接口定义:

[java]
  1. importjava.util.List; 
  2. importcom.foo.arch.entity.id.User;  
  3. importcom.foo.arch.service.ServiceException;  
  4. /** 
  5.  * 维护用户、角色、权限接口
  6.  * @author HenryYan 
  7.  */  
  8. public interface AccountService {  
  9.    
  10.     /** 
  11.      * 添加用户并[同步其他数据库] 
  12.      * <ul> 
  13.      * <li>step 1: 保存系统用户,同时设置和部门的关系</li> 
  14.      * <li>step 2: 同步用户信息到activiti的identity.User,同时设置角色</li> 
  15.      * </ul> 
  16.      * @param user              用户对象 
  17.      * @param orgId             部门ID 
  18.      * @param roleIds           角色ID集合 
  19.      * @param synToActiviti     是否同步到Activiti数据库,通过配置文件方式设置,使用属性:account.user.add.syntoactiviti 
  20.      * @throws OrganizationNotFoundException    关联用户和部门的时候从数据库查询不到哦啊部门对象 
  21.      * @throws  Exception                       其他未知异常 
  22.      */  
  23.     public void save(User user, Long orgId, List<long> roleIds, booleansynToActiviti)  
  24.             throws OrganizationNotFoundException, ServiceException, Exception;  
  25.        
  26.     /** 
  27.      * 删除用户 
  28.      * @param userId        用户ID 
  29.      * @param synToActiviti     是否同步到Activiti数据库,通过配置文件方式设置,使用属性:account.user.add.syntoactiviti 
  30.      * @throws Exception 
  31.      */  
  32.     public void delete(Long userId, booleansynToActiviti) throwsServiceException, Exception;  
  33.    
  34.     /** 
  35.      * 同步用户、角色数据到工作流 
  36.      * @throws Exception 
  37.      */  
  38.     public void synAllUserAndRoleToActiviti() throwsException;  
  39.    
  40.     /** 
  41.      * 删除工作流引擎Activiti的用户、角色以及关系 
  42.      * @throws Exception 
  43.      */  
  44.     public void deleteAllActivitiIdentifyData() throwsException;  
  45. }  

同步单个接口实现片段:

[java]
  1. @Service  
  2. @Transactional  
  3. public class AccountServiceImpl implements AccountService {   
  4.     /** 
  5.      * 保存用户信息,并且同步用户信息到activiti的identity.User和identify.Group 
  6.      * @param user              用户对象{@link User} 
  7.      * @param roleIds           用户拥有的角色ID集合 
  8.      * @param synToActiviti     是否同步数据到Activiti 
  9.      * @see Role 
  10.      */  
  11.     public void saveUser(User user, List<long> roleIds, booleansynToActiviti) {  
  12.         String userId = ObjectUtils.toString(user.getId());  
  13.    
  14.         // 保存系统用户  
  15.         accountManager.saveEntity(user);  
  16.    
  17.         // 同步数据到Activiti Identify模块  
  18.         if(synToActiviti) {  
  19.             UserQuery userQuery = identityService.createUserQuery();  
  20.             List<org.activiti.engine.identity.user> activitiUsers = userQuery.userId(userId).list();  
  21.    
  22.             if(activitiUsers.size() == 1) {  
  23.                 updateActivitiData(user, roleIds, activitiUsers.get(0));  
  24.             }elseif (activitiUsers.size() > 1) {  
  25.                 String errorMsg = "发现重复用户:id="+ userId;  
  26.                 logger.error(errorMsg);  
  27.                 thrownew RuntimeException(errorMsg);  
  28.             }else{  
  29.                 newActivitiUser(user, roleIds);  
  30.             }  
  31.         }  
  32.    
  33.     }  
  34.    
  35.     /** 
  36.      * 添加工作流用户以及角色 
  37.      * @param user      用户对象{@link User} 
  38.      * @param roleIds   用户拥有的角色ID集合 
  39.      */  
  40.     private void newActivitiUser(User user, List<long> roleIds) {  
  41.         String userId = user.getId().toString();  
  42.    
  43.         // 添加用户  
  44.         saveActivitiUser(user);  
  45.    
  46.         // 添加membership  
  47.         addMembershipToIdentify(roleIds, userId);  
  48.     }  
  49.    
  50.     /** 
  51.      * 添加一个用户到Activiti {@link org.activiti.engine.identity.User} 
  52.      * @param user  用户对象, {@link User} 
  53.      */  
  54.     private void saveActivitiUser(User user) {  
  55.         String userId = user.getId().toString();  
  56.         org.activiti.engine.identity.User activitiUser = identityService.newUser(userId);  
  57.         cloneAndSaveActivitiUser(user, activitiUser);  
  58.         logger.debug("add activiti user: {}", ToStringBuilder.reflectionToString(activitiUser));  
  59.     }  
  60.    
  61.     /** 
  62.      * 添加Activiti Identify的用户于组关系 
  63.      * @param roleIds   角色ID集合 
  64.      * @param userId    用户ID 
  65.      */  
  66.     private void addMembershipToIdentify(List<long> roleIds, String userId) {  
  67.         for(Long roleId : roleIds) {  
  68.             Role role = roleManager.getEntity(roleId);  
  69.             logger.debug("add role to activit: {}", role);  
  70.             identityService.createMembership(userId, role.getEnName());  
  71.         }  
  72.     }  
  73.    
  74.     /** 
  75.      * 更新工作流用户以及角色 
  76.      * @param user          用户对象{@link User} 
  77.      * @param roleIds       用户拥有的角色ID集合 
  78.      * @param activitiUser  Activiti引擎的用户对象,{@link org.activiti.engine.identity.User} 
  79.      */  
  80.     private void updateActivitiData(User user, List<long> roleIds, org.activiti.engine.identity.User activitiUser) {  
  81.    
  82.         String userId = user.getId().toString();  
  83.    
  84.         // 更新用户主体信息  
  85.         cloneAndSaveActivitiUser(user, activitiUser);  
  86.    
  87.         // 删除用户的membership  
  88.         List<group> activitiGroups = identityService.createGroupQuery().groupMember(userId).list();  
  89.         for(Group group : activitiGroups) {  
  90.             logger.debug("delete group from activit: {}", ToStringBuilder.reflectionToString(group));  
  91.             identityService.deleteMembership(userId, group.getId());  
  92.         }  
  93.    
  94.         // 添加membership  
  95.         addMembershipToIdentify(roleIds, userId);  
  96.     }  
  97.    
  98.     /** 
  99.      * 使用系统用户对象属性设置到Activiti User对象中 
  100.      * @param user          系统用户对象 
  101.      * @param activitiUser  Activiti User 
  102.      */  
  103.     private void cloneAndSaveActivitiUser(User user, org.activiti.engine.identity.User activitiUser) {  
  104.         activitiUser.setFirstName(user.getName());  
  105.         activitiUser.setLastName(StringUtils.EMPTY);  
  106.         activitiUser.setPassword(StringUtils.EMPTY);  
  107.         activitiUser.setEmail(user.getEmail());  
  108.         identityService.saveUser(activitiUser);  
  109.     }  
  110.    
  111.     @Override  
  112.     public void delete(Long userId, booleansynToActiviti, booleansynToChecking) throwsServiceException, Exception {  
  113.         // 查询需要删除的用户对象  
  114.         User user = accountManager.getEntity(userId);  
  115.         if(user == null) {  
  116.             thrownew ServiceException("删除用户时,找不到ID为"+ userId + "的用户");  
  117.         }  
  118.    
  119.         /** 
  120.          * 同步删除Activiti User Group 
  121.          */  
  122.         if(synToActiviti) {  
  123.             // 同步删除Activiti User  
  124.             List<role> roleList = user.getRoleList();  
  125.             for(Role role : roleList) {  
  126.                 identityService.deleteMembership(userId.toString(), role.getEnName());  
  127.             }  
  128.    
  129.             // 同步删除Activiti User  
  130.             identityService.deleteUser(userId.toString());  
  131.         }  
  132.    
  133.         // 删除本系统用户  
  134.         accountManager.deleteUser(userId);  
  135.    
  136.         // 删除考勤机用户  
  137.         if(synToChecking) {  
  138.             checkingAccountManager.deleteEntity(userId);  
  139.         }  
  140.     }  

同步全部数据接口实现片段:

同步全部数据步骤:

  • 删除Activiti的User、Group、Membership数据

  • 复制Role对象数据到Group

  • 复制用户数据以及Membership数据


ActivitiIdentifyCommonDao.java
[java]
  1. public class ActivitiIdentifyCommonDao {  
  2.     protectedLogger logger = LoggerFactory.getLogger(getClass());  
  3.     @Autowired  
  4.     private JdbcTemplate jdbcTemplate;  
  5.     /** 
  6.      * 删除用户和组的关系 
  7.      */  
  8.     public void deleteAllUser() {  
  9.         String sql = "delete from ACT_ID_USER";  
  10.         jdbcTemplate.execute(sql);  
  11.         logger.debug("deleted from activiti user.");  
  12.     }  
  13.    
  14.     /** 
  15.      * 删除用户和组的关系 
  16.      */  
  17.     public void deleteAllRole() {  
  18.         String sql = "delete from ACT_ID_GROUP";  
  19.         jdbcTemplate.execute(sql);  
  20.         logger.debug("deleted from activiti group.");  
  21.     }  
  22.    
  23.     /** 
  24.      * 删除用户和组的关系 
  25.      */  
  26.     public void deleteAllMemerShip() {  
  27.         String sql = "delete from ACT_ID_MEMBERSHIP";  
  28.         jdbcTemplate.execute(sql);  
  29.         logger.debug("deleted from activiti membership.");  
  30.     }  
  31. }  
ActivitiIdentifyService.java(下面两段代码重复)
  1. public class ActivitiIdentifyService extends AbstractBaseService {  

  2.     @Autowired  
  3.     protected ActivitiIdentifyCommonDao activitiIdentifyCommonDao;  

  4.     /** 
  5.      * 删除用户和组的关系 
  6.      */  
  7.     public void deleteAllUser() {  
  8.         activitiIdentifyCommonDao.deleteAllUser();  
  9.     }  
  10.        
  11.     /** 
  12.      * 删除用户和组的关系 
  13.      */  
  14.     public void deleteAllRole() {  
  15.         activitiIdentifyCommonDao.deleteAllRole();  
  16.     }  
  17.        
  18.     /** 
  19.      * 删除用户和组的关系 
  20.      */  
  21.     public void deleteAllMemerShip() {  
  22.         activitiIdentifyCommonDao.deleteAllMemerShip();  
  23.     }  
  24. }  

publicclass ActivitiIdentifyService extendsAbstractBaseService {
     
    @Autowired
    protectedActivitiIdentifyCommonDao activitiIdentifyCommonDao;
     
    /**
     * 删除用户和组的关系
     */
    publicvoid deleteAllUser() {
        activitiIdentifyCommonDao.deleteAllUser();
    }
     
    /**
     * 删除用户和组的关系
     */
    publicvoid deleteAllRole() {
        activitiIdentifyCommonDao.deleteAllRole();
    }
     
    /**
     * 删除用户和组的关系
     */
    publicvoid deleteAllMemerShip() {
        activitiIdentifyCommonDao.deleteAllMemerShip();
    }
}
AccountServiceImpl.java(下面两段代码重复)
  1. public  class AccountServiceImpl implements AccountService { 
  2.   
  3. @Override  
  4.     public void synAllUserAndRoleToActiviti() throwsException {  
  5.    
  6.         // 清空工作流用户、角色以及关系  
  7.         deleteAllActivitiIdentifyData();  
  8.    
  9.         // 复制角色数据  
  10.         synRoleToActiviti();  
  11.    
  12.         // 复制用户以及关系数据  
  13.         synUserWithRoleToActiviti();  
  14.     }  
  15.    
  16.     /** 
  17.      * 复制用户以及关系数据 
  18.      */  
  19.     private void synUserWithRoleToActiviti() {  
  20.         List<user> allUser = accountManager.getAll();  
  21.         for(User user : allUser) {  
  22.             String userId = user.getId().toString();  
  23.    
  24.             // 添加一个用户到Activiti  
  25.             saveActivitiUser(user);  
  26.    
  27.             // 角色和用户的关系  
  28.             List<role> roleList = user.getRoleList();  
  29.             for(Role role : roleList) {  
  30.                 identityService.createMembership(userId, role.getEnName());  
  31.                 logger.debug("add membership {user: {}, role: {}}", userId, role.getEnName());  
  32.             }  
  33.         }  
  34.     }  
  35.    
  36.     /** 
  37.      * 同步所有角色数据到{@link Group} 
  38.      */  
  39.     private void synRoleToActiviti() {  
  40.         List<role> allRole = roleManager.getAll();  
  41.         for(Role role : allRole) {  
  42.             String groupId = role.getEnName().toString();  
  43.             Group group = identityService.newGroup(groupId);  
  44.             group.setName(role.getName());  
  45.             group.setType(role.getType());  
  46.             identityService.saveGroup(group);  
  47.         }  
  48.     }  
  49.    
  50.     @Override  
  51.     public void deleteAllActivitiIdentifyData() throwsException {  
  52.         activitiIdentifyService.deleteAllMemerShip();  
  53.         activitiIdentifyService.deleteAllRole();  
  54.         activitiIdentifyService.deleteAllUser();  
  55.     }  
  56. }  

publicclass AccountServiceImpl implementsAccountService {
@Override
    publicvoid synAllUserAndRoleToActiviti() throwsException {
 
        // 清空工作流用户、角色以及关系
        deleteAllActivitiIdentifyData();
 
        // 复制角色数据
        synRoleToActiviti();
 
        // 复制用户以及关系数据
        synUserWithRoleToActiviti();
    }
 
    /**
     * 复制用户以及关系数据
     */
    privatevoid synUserWithRoleToActiviti() {
        List<user> allUser = accountManager.getAll();
        for(User user : allUser) {
            String userId = user.getId().toString();
 
            // 添加一个用户到Activiti
            saveActivitiUser(user);
 
            // 角色和用户的关系
            List<role> roleList = user.getRoleList();
            for(Role role : roleList) {
                identityService.createMembership(userId, role.getEnName());
                logger.debug("add membership {user: {}, role: {}}", userId, role.getEnName());
            }
        }
    }
 
    /**
     * 同步所有角色数据到{@link Group}
     */
    privatevoid synRoleToActiviti() {
        List<role> allRole = roleManager.getAll();
        for(Role role : allRole) {
            String groupId = role.getEnName().toString();
            Group group = identityService.newGroup(groupId);
            group.setName(role.getName());
            group.setType(role.getType());
            identityService.saveGroup(group);
        }
    }
 
    @Override
    publicvoid deleteAllActivitiIdentifyData() throwsException {
        activitiIdentifyService.deleteAllMemerShip();
        activitiIdentifyService.deleteAllRole();
        activitiIdentifyService.deleteAllUser();
    }
}

方案二:覆盖IdentifyService接口的实现

此方法覆盖IdentifyService接口的默认实现类:org.activiti.engine.impl.IdentityServiceImpl

读者可以根据现有的用户管理接口实现覆盖IdentityServiceImpl的每个方法的默认实现,这样就等于放弃使用系列表:ACT_ID_。

此方法不再提供代码,请读者自行根据现有接口逐一实现接口定义的功能。

方案三:用视图覆盖同名的ACT_ID_系列表

此方案和第二种类似,放弃使用系列表:ACT_ID_,创建同名的视图。

1.删除已创建的ACT_ID_*表

创建视图必须删除引擎自动创建的ACT_ID_*表,否则不能创建视图。

2.创建视图:

  • ACT_ID_GROUP
  • ACT_ID_INFO
  • ACT_ID_MEMBERSHIP
  • ACT_ID_USER

创建的视图要保证数据类型一致,例如用户的ACT_ID_MEMBERSHIP表的两个字段都是字符型,一般系统中都是用NUMBER作为用户、角色的主键类型,所以创建视图的时候要把数字类型转换为字符型。

3.修改引擎默认配置

在引擎配置中设置属性dbIdentityUsedfalse即可。

  1. <beanidbeanid="processEngineConfiguration"class="org.activiti.spring.SpringProcessEngineConfiguration">  
  2.     ...  
  3.     <propertynamepropertyname="dbIdentityUsed"ref="false">  
  4.     ...  
  5. </property></bean>  
<beanid="processEngineConfiguration"class="org.activiti.spring.SpringProcessEngineConfiguration">
    ...
    <propertyname="dbIdentityUsed"ref="false">
    ...
</property></bean>

总结
  • 方案:不破坏、不修改源码,面向接口编程推荐

  • 方案:放弃原有的Identify模块,使用自定义的实现,特殊情况可以使用此方式;

  • 方案:不需要编写Java代码,只需要创建同名视图即可对于现有系统的集成、强烈推荐

原文地址:https://www.cnblogs.com/llhl/p/9648691.html