zoukankan      html  css  js  c++  java
  • 项目中加入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代码,只需要创建同名视图即可对于现有系统的集成、强烈推荐

  • 相关阅读:
    正则表达式
    DNS协议相关命令 dig
    Linux下 redsocks + iptables + socks5 实现全局代理
    Kotlin native 初心
    Kotlin 初心
    XMLHttpRequest2 实现AJAX跨域请求
    CSS、JavaScript 初心
    jQuery 初心
    java.lang.ClassNotFoundException 解决方案
    CPU 负荷过重时邮件报警
  • 原文地址:https://www.cnblogs.com/llhl/p/9648691.html
Copyright © 2011-2022 走看看