前面主要介紹了元數據管理和業務數據的處理,一般一個系統都會有多個用戶,不一樣用戶具備不一樣的權限,本文主要介紹基於RBAC動態權限管理在crudapi中的實現。java
RBAC權限模型(Role-Based Access Control)即:基於角色的權限控制。模型中有幾個關鍵的術語:
用戶:系統接口及訪問的操做者
權限:可以訪問某接口或者作某操做的受權資格
角色:具備一類相同操做權限的用戶的總稱 api
一個用戶有一個或多個角色
一個角色包含多個用戶
一個角色有多種權限
一個權限屬於多個角色 安全
Spring Security是Spring項目組中用來提供安全認證服務的框架,能夠很方便的實現動態權限管理。框架
系統內置5個表單,這些表單和權限相關,和具體業務無關ide
其中url是ANT格式表達式,用於配置url來肯定是否擁有某個資源的權限。測試
用戶表記錄登陸用戶信息this
角色url
用戶和角色的中間表,參考以前表關係管理,利用兩個一對多創建多對多關係,3d
角色和資源的中間表,一樣的利用兩個一對多創建多對多關係 code
原表 | 目標表 | 關係 |
---|---|---|
user | userRoleLine | 一對多 |
userRoleLine | role | 多對一 |
role | roleResourceLine | 一對多 |
roleResourceLine | resource | 多對一 |
根據登陸用戶首選獲取角色列表,每一個角色對應多個資源,最終用戶的權限爲多個角色對應的資源疊加。若是擁有某個資源權限就返回數據,不然提示無權限。
默認若是沒有匹配任何資源,表示該資源無需特別權限,只須要登陸用戶便可。
添加客戶資源,ANT url爲/api/business/customer/*,操做爲,表示GET,PATCH,DELETE,POST都須要受權。
若是操做爲DELETE,表示值控制DELETE操做,其它操做不限制。
經過UI訪問客戶時候提示沒有權限,和指望的效果一致
添加角色「客戶管理員」,該角色擁有客戶訪問權限
給「超級管理員」添加「客戶管理員」角色,這樣「超級管理員」就擁有了客戶訪問權限
由於用戶從新分配了角色,須要須要註銷從新登陸,登陸以後又能夠正常訪問客戶資源了。
@Slf4j @Component public class DynamicSecurityMetadataSource implements FilterInvocationSecurityMetadataSource { private static Map<String, ConfigAttribute> configAttributeMap = null; @Autowired private DynamicSecurityService dynamicSecurityService; @PostConstruct public void loadDataSource() { configAttributeMap = dynamicSecurityService.loadDataSource(); } public void clearDataSource() { log.info("DynamicSecurityMetadataSource clearDataSource"); configAttributeMap.clear(); configAttributeMap = null; } @Override public Collection<ConfigAttribute> getAttributes(Object o) throws IllegalArgumentException { if (configAttributeMap == null) { this.loadDataSource(); } List<ConfigAttribute> configAttributes = new ArrayList<>(); FilterInvocation fi = (FilterInvocation) o; String method = fi.getRequest().getMethod(); log.info("getAttributes method = " + method); //獲取當前訪問的路徑 String url = fi.getRequestUrl(); String path = URLUtil.getPath(url) + "_"+ method; log.info("getAttributes url = " + url); log.info("getAttributes path = " + path); PathMatcher pathMatcher = new AntPathMatcher(); Iterator<String> iterator = configAttributeMap.keySet().iterator(); //獲取訪問該路徑所需資源 while (iterator.hasNext()) { String pattern = iterator.next(); if (pathMatcher.match(pattern, path)) { log.info("match success = " + pattern + ", " + path); configAttributes.add(configAttributeMap.get(pattern)); } } // 未設置操做請求權限,返回空集合 return configAttributes; } @Override public Collection<ConfigAttribute> getAllConfigAttributes() { return null; } @Override public boolean supports(Class<?> aClass) { return true; } }
繼承FilterInvocationSecurityMetadataSource,實現getAttributes接口,經過http url加http method進行匹配
@Slf4j @Component public class DynamicAccessDecisionManager implements AccessDecisionManager { @Override public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes) throws AccessDeniedException, InsufficientAuthenticationException { // 當接口未被配置資源時直接放行 if (CollUtil.isEmpty(configAttributes)) { log.info("empty configAttributes decide passed!"); return; } FilterInvocation fi = (FilterInvocation) object; String method = fi.getRequest().getMethod(); log.info("decide method = " + method); List<String> needAuthorityList = new ArrayList<String>(); Iterator<ConfigAttribute> iterator = configAttributes.iterator(); while (iterator.hasNext()) { ConfigAttribute configAttribute = iterator.next(); //將訪問所需資源或用戶擁有資源進行比對 String needAuthority = configAttribute.getAttribute(); needAuthorityList.add(needAuthority); for (GrantedAuthority grantedAuthority : authentication.getAuthorities()) { if (needAuthority.trim().equals(grantedAuthority.getAuthority())) { return; } } } throw new AccessDeniedException("對不起,您沒有資源:" + String.join(",", needAuthorityList) +"的訪問權限!"); } @Override public boolean supports(ConfigAttribute configAttribute) { return true; } @Override public boolean supports(Class<?> aClass) { return true; } }
繼承AccessDecisionManager,實現decide接口,將訪問所需資源或用戶擁有資源進行比對,若是擁有權限則放行,不然提示無權限。
本文介紹了RBAC在crudapi中的實現原理,首先引入Spring security框架,而後利用配置生成用戶,角色,資源等表單,經過配置實現基本的CRUD功能,最終實現了動態權限精細化管理。由於用戶,角色等表與業務無關,因此會做爲系統內置表單。
本系統屬於產品級的零代碼平臺,不一樣於自動代碼生成器,不須要生成Controller、Service、Repository、Entity等業務代碼,程序運行起來就能夠使用,真正0代碼,能夠覆蓋基本的和業務無關的CRUD RESTful API。
官網地址:https://crudapi.cn
測試地址:https://demo.crudapi.cn/crudapi/login