您好,登錄后才能下訂單哦!
小編給大家分享一下flowable工作流引擎如何實現(xiàn)自定義權(quán)限管理,希望大家閱讀完這篇文章之后都有所收獲,下面讓我們一起去探討吧!
場景: 對已有系統(tǒng)集成工作流,系統(tǒng)已經(jīng)有一整套的權(quán)限管理模塊,并且后期需要改造為單獨的微服務,無法簡單通過網(wǎng)上的建立視圖進行解決,同時考慮到數(shù)據(jù)同步到 flowable 的方式,需要改造現(xiàn)有系統(tǒng)的代碼,后期如果接入無人維護的系統(tǒng),比較麻煩。如果選擇自定義查詢,可以更靈活定制。雖然會有一定的開發(fā)工作量,但比較符合目前的系統(tǒng)現(xiàn)狀。
想法:參考 集成 LDAP 的實現(xiàn)方式
可以覆蓋IdmIdentityServiceImpl類,或者直接實現(xiàn)IdmIdentityService接口,并使用實現(xiàn)類作為ProcessEngineConfiguration中的idmIdentityService參數(shù)。
參考 LDAPIdentityServiceImpl 的注冊到 flowable 引擎配置類的實現(xiàn)方式
在SpringBoot中,可以向ProcessEngineConfigurationbean定義添加下面的代碼實現(xiàn):
@Bean public EngineConfigurationConfigurer<SpringIdmEngineConfiguration> MyIdmEngineConfigurer() { return idmEngineConfiguration -> idmEngineConfiguration .setIdmIdentityService(new IdmIdentityServiceHandler()); }
其中 IdmIdentityServiceHandler 同樣參考 LDAPIdentityServiceImpl 繼承 IdmIdentityServiceImpl 進行處理。
package com.jxlgzwh.handler; import org.flowable.common.engine.api.FlowableException; import org.flowable.idm.api.*; import org.flowable.idm.engine.impl.IdmIdentityServiceImpl; import org.flowable.idm.engine.impl.persistence.entity.GroupEntityImpl; import org.flowable.idm.engine.impl.persistence.entity.UserEntityImpl; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.List; public class IdmIdentityServiceHandler extends IdmIdentityServiceImpl { private static final Logger LOGGER = LoggerFactory.getLogger(IdmIdentityServiceHandler.class); @Override public UserQuery createUserQuery() { System.out.println("用戶查詢--"); return null; } @Override public GroupQuery createGroupQuery() { System.out.println("用戶組查詢--"); return null; } @Override public boolean checkPassword(String userId, String password) { return true; } @Override public List<Group> getGroupsWithPrivilege(String name) { System.out.println("查詢--"); throw new FlowableException("LDAP identity service doesn't support creating a new user"); } @Override public List<User> getUsersWithPrivilege(String name) { System.out.println("查詢--"); throw new FlowableException("LDAP identity service doesn't support creating a new user"); } @Override public User newUser(String userId) { throw new FlowableException("LDAP identity service doesn't support creating a new user"); } @Override public void saveUser(User user) { throw new FlowableException("LDAP identity service doesn't support saving an user"); } @Override public NativeUserQuery createNativeUserQuery() { throw new FlowableException("LDAP identity service doesn't support native querying"); } @Override public void deleteUser(String userId) { throw new FlowableException("LDAP identity service doesn't support deleting an user"); } @Override public Group newGroup(String groupId) { throw new FlowableException("LDAP identity service doesn't support creating a new group"); } @Override public NativeGroupQuery createNativeGroupQuery() { throw new FlowableException("LDAP identity service doesn't support native querying"); } @Override public void saveGroup(Group group) { throw new FlowableException("LDAP identity service doesn't support saving a group"); } @Override public void deleteGroup(String groupId) { throw new FlowableException("LDAP identity service doesn't support deleting a group"); } }
考慮到不需要對 flowable 的 權(quán)限進行維護,所以無需實現(xiàn) 新增 和修改方法。
驗證: 寫個方法進行測試是否生效
@RequestMapping(value = "is") @ResponseBody public String identityService() { identityService.createUserQuery(); return "測試"; }
訪問方法,后臺打印 “用戶查詢--“ 表明配置成功。
集成 LDAP 的完整代碼 可以在GitHub查看代碼:LDAPIdentityServiceImpl。
其中 用戶查詢 LDAPUserQueryImpl 繼承了 UserQueryImpl ; 用戶組查詢 LDAPGroupQueryImpl extends GroupQueryImpl
/* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.flowable.ldap.impl; import java.util.ArrayList; import java.util.List; import javax.naming.NamingEnumeration; import javax.naming.NamingException; import javax.naming.directory.InitialDirContext; import javax.naming.directory.SearchControls; import javax.naming.directory.SearchResult; import org.flowable.common.engine.impl.interceptor.CommandContext; import org.flowable.idm.api.User; import org.flowable.idm.engine.impl.UserQueryImpl; import org.flowable.idm.engine.impl.persistence.entity.UserEntity; import org.flowable.idm.engine.impl.persistence.entity.UserEntityImpl; import org.flowable.ldap.LDAPCallBack; import org.flowable.ldap.LDAPConfiguration; import org.flowable.ldap.LDAPTemplate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class LDAPUserQueryImpl extends UserQueryImpl { private static final long serialVersionUID = 1L; private static final Logger LOGGER = LoggerFactory.getLogger(LDAPUserQueryImpl.class); protected LDAPConfiguration ldapConfigurator; public LDAPUserQueryImpl(LDAPConfiguration ldapConfigurator) { this.ldapConfigurator = ldapConfigurator; } @Override public long executeCount(CommandContext commandContext) { return executeQuery().size(); } @Override public List<User> executeList(CommandContext commandContext) { return executeQuery(); } protected List<User> executeQuery() { if (getId() != null) { List<User> result = new ArrayList<>(); result.add(findById(getId())); return result; } else if (getIdIgnoreCase() != null) { List<User> result = new ArrayList<>(); result.add(findById(getIdIgnoreCase())); return result; } else if (getFullNameLike() != null) { return executeNameQuery(getFullNameLike()); } else if (getFullNameLikeIgnoreCase() != null) { return executeNameQuery(getFullNameLikeIgnoreCase()); } else { return executeAllUserQuery(); } } protected List<User> executeNameQuery(String name) { String fullName = name.replaceAll("%", ""); String searchExpression = ldapConfigurator.getLdapQueryBuilder().buildQueryByFullNameLike(ldapConfigurator, fullName); return executeUsersQuery(searchExpression); } protected List<User> executeAllUserQuery() { String searchExpression = ldapConfigurator.getQueryAllUsers(); return executeUsersQuery(searchExpression); } protected UserEntity findById(final String userId) { LDAPTemplate ldapTemplate = new LDAPTemplate(ldapConfigurator); return ldapTemplate.execute(new LDAPCallBack<UserEntity>() { @Override public UserEntity executeInContext(InitialDirContext initialDirContext) { try { String searchExpression = ldapConfigurator.getLdapQueryBuilder().buildQueryByUserId(ldapConfigurator, userId); String baseDn = ldapConfigurator.getUserBaseDn() != null ? ldapConfigurator.getUserBaseDn() : ldapConfigurator.getBaseDn(); NamingEnumeration<?> namingEnum = initialDirContext.search(baseDn, searchExpression, createSearchControls()); UserEntity user = new UserEntityImpl(); while (namingEnum.hasMore()) { // Should be only one SearchResult result = (SearchResult) namingEnum.next(); mapSearchResultToUser(result, user); } namingEnum.close(); return user; } catch (NamingException ne) { LOGGER.error("Could not find user {} : {}", userId, ne.getMessage(), ne); return null; } } }); } protected List<User> executeUsersQuery(final String searchExpression) { LDAPTemplate ldapTemplate = new LDAPTemplate(ldapConfigurator); return ldapTemplate.execute(new LDAPCallBack<List<User>>() { @Override public List<User> executeInContext(InitialDirContext initialDirContext) { List<User> result = new ArrayList<>(); try { String baseDn = ldapConfigurator.getUserBaseDn() != null ? ldapConfigurator.getUserBaseDn() : ldapConfigurator.getBaseDn(); NamingEnumeration<?> namingEnum = initialDirContext.search(baseDn, searchExpression, createSearchControls()); while (namingEnum.hasMore()) { SearchResult searchResult = (SearchResult) namingEnum.next(); UserEntity user = new UserEntityImpl(); mapSearchResultToUser(searchResult, user); result.add(user); } namingEnum.close(); } catch (NamingException ne) { LOGGER.debug("Could not execute LDAP query: {}", ne.getMessage(), ne); return null; } return result; } }); } protected void mapSearchResultToUser(SearchResult result, UserEntity user) throws NamingException { if (ldapConfigurator.getUserIdAttribute() != null) { user.setId(result.getAttributes().get(ldapConfigurator.getUserIdAttribute()).get().toString()); } if (ldapConfigurator.getUserFirstNameAttribute() != null) { try { user.setFirstName(result.getAttributes().get(ldapConfigurator.getUserFirstNameAttribute()).get().toString()); } catch (NullPointerException e) { user.setFirstName(""); } } if (ldapConfigurator.getUserLastNameAttribute() != null) { try { user.setLastName(result.getAttributes().get(ldapConfigurator.getUserLastNameAttribute()).get().toString()); } catch (NullPointerException e) { user.setLastName(""); } } if (ldapConfigurator.getUserEmailAttribute() != null) { try { user.setEmail(result.getAttributes().get(ldapConfigurator.getUserEmailAttribute()).get().toString()); } catch (NullPointerException e) { user.setEmail(""); } } } protected SearchControls createSearchControls() { SearchControls searchControls = new SearchControls(); searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE); searchControls.setTimeLimit(ldapConfigurator.getSearchTimeLimit()); return searchControls; } }
/* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.flowable.ldap.impl; import java.util.ArrayList; import java.util.List; import javax.naming.NamingEnumeration; import javax.naming.NamingException; import javax.naming.directory.InitialDirContext; import javax.naming.directory.SearchControls; import javax.naming.directory.SearchResult; import org.flowable.common.engine.api.FlowableException; import org.flowable.common.engine.impl.interceptor.CommandContext; import org.flowable.idm.api.Group; import org.flowable.idm.engine.impl.GroupQueryImpl; import org.flowable.idm.engine.impl.persistence.entity.GroupEntity; import org.flowable.idm.engine.impl.persistence.entity.GroupEntityImpl; import org.flowable.ldap.LDAPCallBack; import org.flowable.ldap.LDAPConfiguration; import org.flowable.ldap.LDAPGroupCache; import org.flowable.ldap.LDAPTemplate; public class LDAPGroupQueryImpl extends GroupQueryImpl { private static final long serialVersionUID = 1L; protected LDAPConfiguration ldapConfigurator; protected LDAPGroupCache ldapGroupCache; public LDAPGroupQueryImpl(LDAPConfiguration ldapConfigurator, LDAPGroupCache ldapGroupCache) { this.ldapConfigurator = ldapConfigurator; this.ldapGroupCache = ldapGroupCache; } @Override public long executeCount(CommandContext commandContext) { return executeQuery().size(); } @Override public List<Group> executeList(CommandContext commandContext) { return executeQuery(); } protected List<Group> executeQuery() { if (getUserId() != null) { return findGroupsByUser(getUserId()); } else if (getId() != null) { return findGroupsById(getId()); } else { return findAllGroups(); } } protected List<Group> findGroupsByUser(String userId) { // First try the cache (if one is defined) if (ldapGroupCache != null) { List<Group> groups = ldapGroupCache.get(userId); if (groups != null) { return groups; } } String searchExpression = ldapConfigurator.getLdapQueryBuilder().buildQueryGroupsForUser(ldapConfigurator, userId); List<Group> groups = executeGroupQuery(searchExpression); // Cache results for later if (ldapGroupCache != null) { ldapGroupCache.add(userId, groups); } return groups; } protected List<Group> findGroupsById(String id) { String searchExpression = ldapConfigurator.getLdapQueryBuilder().buildQueryGroupsById(ldapConfigurator, id); return executeGroupQuery(searchExpression); } protected List<Group> findAllGroups() { String searchExpression = ldapConfigurator.getQueryAllGroups(); List<Group> groups = executeGroupQuery(searchExpression); return groups; } protected List<Group> executeGroupQuery(final String searchExpression) { LDAPTemplate ldapTemplate = new LDAPTemplate(ldapConfigurator); return ldapTemplate.execute(new LDAPCallBack<List<Group>>() { @Override public List<Group> executeInContext(InitialDirContext initialDirContext) { List<Group> groups = new ArrayList<>(); try { String baseDn = ldapConfigurator.getGroupBaseDn() != null ? ldapConfigurator.getGroupBaseDn() : ldapConfigurator.getBaseDn(); NamingEnumeration<?> namingEnum = initialDirContext.search(baseDn, searchExpression, createSearchControls()); while (namingEnum.hasMore()) { // Should be only one SearchResult result = (SearchResult) namingEnum.next(); GroupEntity group = new GroupEntityImpl(); if (ldapConfigurator.getGroupIdAttribute() != null) { group.setId(result.getAttributes().get(ldapConfigurator.getGroupIdAttribute()).get().toString()); } if (ldapConfigurator.getGroupNameAttribute() != null) { group.setName(result.getAttributes().get(ldapConfigurator.getGroupNameAttribute()).get().toString()); } if (ldapConfigurator.getGroupTypeAttribute() != null) { group.setType(result.getAttributes().get(ldapConfigurator.getGroupTypeAttribute()).get().toString()); } groups.add(group); } namingEnum.close(); return groups; } catch (NamingException e) { throw new FlowableException("Could not find groups " + searchExpression, e); } } }); } protected SearchControls createSearchControls() { SearchControls searchControls = new SearchControls(); searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE); searchControls.setTimeLimit(ldapConfigurator.getSearchTimeLimit()); return searchControls; } }
根據(jù)自己的業(yè)務需要,提供用戶的管理功能。關(guān)鍵部分:
配置IdmEngineConfiguration參數(shù)
實現(xiàn)IdmIdentityService,可繼承IdmIdentityServiceImpl
實現(xiàn)UserQuery,可繼承UserQueryImpl
實現(xiàn)GroupQuery,可繼承GroupQueryImpl
實現(xiàn)PrivilegeQuery,可繼承PrivilegeQueryImpl
相當于做自己的權(quán)限管理系統(tǒng)的查詢客戶端。
看完了這篇文章,相信你對“flowable工作流引擎如何實現(xiàn)自定義權(quán)限管理”有了一定的了解,如果想了解更多相關(guān)知識,歡迎關(guān)注億速云行業(yè)資訊頻道,感謝各位的閱讀!
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。