项目中加入activiti后,用户权限管理处理的三种方式
同步或者重构Activiti Identify用户数据的多种方案比较
相信每个涉及到用户的系统都有一套用户权限管理平台或者模块,用来维护用户以及在系统内的功能、数据权限,我们使用的Activiti工作流引擎配套设计了包括User、Group的Identify模块,怎么和业务数据同步呢,这个问题是每个新人必问的问题之一,下面介绍几种同步方案,最后总结比较。
方案一:调用IdentifyService接口完成同步
参考IdentifyService接口Javadoc:http://www.activiti.org/javadocs/org/activiti/engine/IdentityService.html
- importjava.util.List;
- importcom.foo.arch.entity.id.User;
- importcom.foo.arch.service.ServiceException;
- /**
- * 维护用户、角色、权限接口
- * @author HenryYan
- */
- public interface AccountService {
- /**
- * 添加用户并[同步其他数据库]
- * <ul>
- * <li>step 1: 保存系统用户,同时设置和部门的关系</li>
- * <li>step 2: 同步用户信息到activiti的identity.User,同时设置角色</li>
- * </ul>
- * @param user 用户对象
- * @param orgId 部门ID
- * @param roleIds 角色ID集合
- * @param synToActiviti 是否同步到Activiti数据库,通过配置文件方式设置,使用属性:account.user.add.syntoactiviti
- * @throws OrganizationNotFoundException 关联用户和部门的时候从数据库查询不到哦啊部门对象
- * @throws Exception 其他未知异常
- */
- public void save(User user, Long orgId, List<long> roleIds, booleansynToActiviti)
- throws OrganizationNotFoundException, ServiceException, Exception;
- /**
- * 删除用户
- * @param userId 用户ID
- * @param synToActiviti 是否同步到Activiti数据库,通过配置文件方式设置,使用属性:account.user.add.syntoactiviti
- * @throws Exception
- */
- public void delete(Long userId, booleansynToActiviti) throwsServiceException, Exception;
- /**
- * 同步用户、角色数据到工作流
- * @throws Exception
- */
- public void synAllUserAndRoleToActiviti() throwsException;
- /**
- * 删除工作流引擎Activiti的用户、角色以及关系
- * @throws Exception
- */
- public void deleteAllActivitiIdentifyData() throwsException;
- }
同步单个接口实现片段:
- @Service
- @Transactional
- public class AccountServiceImpl implements AccountService {
- /**
- * 保存用户信息,并且同步用户信息到activiti的identity.User和identify.Group
- * @param user 用户对象{@link User}
- * @param roleIds 用户拥有的角色ID集合
- * @param synToActiviti 是否同步数据到Activiti
- * @see Role
- */
- public void saveUser(User user, List<long> roleIds, booleansynToActiviti) {
- String userId = ObjectUtils.toString(user.getId());
- // 保存系统用户
- accountManager.saveEntity(user);
- // 同步数据到Activiti Identify模块
- if(synToActiviti) {
- UserQuery userQuery = identityService.createUserQuery();
- List<org.activiti.engine.identity.user> activitiUsers = userQuery.userId(userId).list();
- if(activitiUsers.size() == 1) {
- updateActivitiData(user, roleIds, activitiUsers.get(0));
- }elseif (activitiUsers.size() > 1) {
- String errorMsg = "发现重复用户:id="+ userId;
- logger.error(errorMsg);
- thrownew RuntimeException(errorMsg);
- }else{
- newActivitiUser(user, roleIds);
- }
- }
- }
- /**
- * 添加工作流用户以及角色
- * @param user 用户对象{@link User}
- * @param roleIds 用户拥有的角色ID集合
- */
- private void newActivitiUser(User user, List<long> roleIds) {
- String userId = user.getId().toString();
- // 添加用户
- saveActivitiUser(user);
- // 添加membership
- addMembershipToIdentify(roleIds, userId);
- }
- /**
- * 添加一个用户到Activiti {@link org.activiti.engine.identity.User}
- * @param user 用户对象, {@link User}
- */
- private void saveActivitiUser(User user) {
- String userId = user.getId().toString();
- org.activiti.engine.identity.User activitiUser = identityService.newUser(userId);
- cloneAndSaveActivitiUser(user, activitiUser);
- logger.debug("add activiti user: {}", ToStringBuilder.reflectionToString(activitiUser));
- }
- /**
- * 添加Activiti Identify的用户于组关系
- * @param roleIds 角色ID集合
- * @param userId 用户ID
- */
- private void addMembershipToIdentify(List<long> roleIds, String userId) {
- for(Long roleId : roleIds) {
- Role role = roleManager.getEntity(roleId);
- logger.debug("add role to activit: {}", role);
- identityService.createMembership(userId, role.getEnName());
- }
- }
- /**
- * 更新工作流用户以及角色
- * @param user 用户对象{@link User}
- * @param roleIds 用户拥有的角色ID集合
- * @param activitiUser Activiti引擎的用户对象,{@link org.activiti.engine.identity.User}
- */
- private void updateActivitiData(User user, List<long> roleIds, org.activiti.engine.identity.User activitiUser) {
- String userId = user.getId().toString();
- // 更新用户主体信息
- cloneAndSaveActivitiUser(user, activitiUser);
- // 删除用户的membership
- List<group> activitiGroups = identityService.createGroupQuery().groupMember(userId).list();
- for(Group group : activitiGroups) {
- logger.debug("delete group from activit: {}", ToStringBuilder.reflectionToString(group));
- identityService.deleteMembership(userId, group.getId());
- }
- // 添加membership
- addMembershipToIdentify(roleIds, userId);
- }
- /**
- * 使用系统用户对象属性设置到Activiti User对象中
- * @param user 系统用户对象
- * @param activitiUser Activiti User
- */
- private void cloneAndSaveActivitiUser(User user, org.activiti.engine.identity.User activitiUser) {
- activitiUser.setFirstName(user.getName());
- activitiUser.setLastName(StringUtils.EMPTY);
- activitiUser.setPassword(StringUtils.EMPTY);
- activitiUser.setEmail(user.getEmail());
- identityService.saveUser(activitiUser);
- }
- @Override
- public void delete(Long userId, booleansynToActiviti, booleansynToChecking) throwsServiceException, Exception {
- // 查询需要删除的用户对象
- User user = accountManager.getEntity(userId);
- if(user == null) {
- thrownew ServiceException("删除用户时,找不到ID为"+ userId + "的用户");
- }
- /**
- * 同步删除Activiti User Group
- */
- if(synToActiviti) {
- // 同步删除Activiti User
- List<role> roleList = user.getRoleList();
- for(Role role : roleList) {
- identityService.deleteMembership(userId.toString(), role.getEnName());
- }
- // 同步删除Activiti User
- identityService.deleteUser(userId.toString());
- }
- // 删除本系统用户
- accountManager.deleteUser(userId);
- // 删除考勤机用户
- if(synToChecking) {
- checkingAccountManager.deleteEntity(userId);
- }
- }
- }
同步全部数据步骤:
-
删除Activiti的User、Group、Membership数据
-
复制Role对象数据到Group
-
复制用户数据以及Membership数据
ActivitiIdentifyCommonDao.java
- public class ActivitiIdentifyCommonDao {
- protectedLogger logger = LoggerFactory.getLogger(getClass());
- @Autowired
- private JdbcTemplate jdbcTemplate;
- /**
- * 删除用户和组的关系
- */
- public void deleteAllUser() {
- String sql = "delete from ACT_ID_USER";
- jdbcTemplate.execute(sql);
- logger.debug("deleted from activiti user.");
- }
- /**
- * 删除用户和组的关系
- */
- public void deleteAllRole() {
- String sql = "delete from ACT_ID_GROUP";
- jdbcTemplate.execute(sql);
- logger.debug("deleted from activiti group.");
- }
- /**
- * 删除用户和组的关系
- */
- public void deleteAllMemerShip() {
- String sql = "delete from ACT_ID_MEMBERSHIP";
- jdbcTemplate.execute(sql);
- logger.debug("deleted from activiti membership.");
- }
- }
ActivitiIdentifyService.java(下面两段代码重复)
- public class ActivitiIdentifyService extends AbstractBaseService {
- @Autowired
- protected ActivitiIdentifyCommonDao activitiIdentifyCommonDao;
- /**
- * 删除用户和组的关系
- */
- public void deleteAllUser() {
- activitiIdentifyCommonDao.deleteAllUser();
- }
- /**
- * 删除用户和组的关系
- */
- public void deleteAllRole() {
- activitiIdentifyCommonDao.deleteAllRole();
- }
- /**
- * 删除用户和组的关系
- */
- public void deleteAllMemerShip() {
- activitiIdentifyCommonDao.deleteAllMemerShip();
- }
- }
publicclass ActivitiIdentifyService extendsAbstractBaseService {
@Autowired
protectedActivitiIdentifyCommonDao activitiIdentifyCommonDao;
/**
* 删除用户和组的关系
*/
publicvoid deleteAllUser() {
activitiIdentifyCommonDao.deleteAllUser();
}
/**
* 删除用户和组的关系
*/
publicvoid deleteAllRole() {
activitiIdentifyCommonDao.deleteAllRole();
}
/**
* 删除用户和组的关系
*/
publicvoid deleteAllMemerShip() {
activitiIdentifyCommonDao.deleteAllMemerShip();
}
}
AccountServiceImpl.java(下面两段代码重复)
- public class AccountServiceImpl implements AccountService {
- @Override
- public void synAllUserAndRoleToActiviti() throwsException {
- // 清空工作流用户、角色以及关系
- deleteAllActivitiIdentifyData();
- // 复制角色数据
- synRoleToActiviti();
- // 复制用户以及关系数据
- synUserWithRoleToActiviti();
- }
- /**
- * 复制用户以及关系数据
- */
- private void 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}
- */
- private void 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
- public void deleteAllActivitiIdentifyData() throwsException {
- activitiIdentifyService.deleteAllMemerShip();
- activitiIdentifyService.deleteAllRole();
- activitiIdentifyService.deleteAllUser();
- }
- }
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.修改引擎默认配置
在引擎配置中设置属性dbIdentityUsed为false即可。
- <beanidbeanid="processEngineConfiguration"class="org.activiti.spring.SpringProcessEngineConfiguration">
- ...
- <propertynamepropertyname="dbIdentityUsed"ref="false">
- ...
- </property></bean>
<beanid="processEngineConfiguration"class="org.activiti.spring.SpringProcessEngineConfiguration">
...
<propertyname="dbIdentityUsed"ref="false">
...
</property></bean>
-
方案一:不破坏、不修改源码,面向接口编程,推荐;
-
方案二:放弃原有的Identify模块,使用自定义的实现,特殊情况可以使用此方式;
-
方案三:不需要编写Java代码,只需要创建同名视图即可,对于现有系统的集成、强烈推荐;
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步