1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        基于角色訪問控制RBAC權(quán)限模型的動(dòng)態(tài)資源訪問權(quán)限管理實(shí)現(xiàn)

        共 5302字,需瀏覽 11分鐘

         ·

        2021-02-28 12:23

        RBAC權(quán)限模型(Role-Based Access Control)

        前面主要介紹了元數(shù)據(jù)管理和業(yè)務(wù)數(shù)據(jù)的處理,通常一個(gè)系統(tǒng)都會(huì)有多個(gè)用戶,不同用戶具有不同的權(quán)限,本文主要介紹基于RBAC動(dòng)態(tài)權(quán)限管理在crudapi中的實(shí)現(xiàn)。


        概要


        RBAC簡介


        RBAC權(quán)限模型(Role-Based Access Control)即:基于角色的權(quán)限控制。模型中有幾個(gè)關(guān)鍵的術(shù)語:

        用戶:系統(tǒng)接口及訪問的操作者

        權(quán)限:能夠訪問某接口或者做某操作的授權(quán)資格

        角色:具有一類相同操作權(quán)限的用戶的總稱


        用戶角色權(quán)限關(guān)系


        一個(gè)用戶有一個(gè)或多個(gè)角色

        一個(gè)角色包含多個(gè)用戶

        一個(gè)角色有多種權(quán)限

        一個(gè)權(quán)限屬于多個(gè)角色


        Spring security


        Spring Security是Spring項(xiàng)目組中用來提供安全認(rèn)證服務(wù)的框架,可以很方便的實(shí)現(xiàn)動(dòng)態(tài)權(quán)限管理。


        表單配置


        系統(tǒng)內(nèi)置5個(gè)表單,這些表單和權(quán)限相關(guān),和具體業(yè)務(wù)無關(guān)


        資源resource


        resource?其中url是ANT格式表達(dá)式,用于配置url來確定是否擁有某個(gè)資源的權(quán)限。


        用戶user


        user?用戶表記錄登錄用戶信息


        角色role


        role?角色


        用戶角色行userRoleLine


        userRoleLine?用戶和角色的中間表,參考之前表關(guān)系管理,利用兩個(gè)一對多建立多對多關(guān)系,


        角色資源行roleResourceLine


        roleResourceLine?角色和資源的中間表,同樣的利用兩個(gè)一對多建立多對多關(guān)系


        表關(guān)系


        relation


        原表目標(biāo)表關(guān)系useruserRoleLine一對多userRoleLinerole多對一roleroleResourceLine一對多roleResourceLineresource多對一


        權(quán)限控制原理


        根據(jù)登錄用戶首選獲取角色列表,每個(gè)角色對應(yīng)多個(gè)資源,最終用戶的權(quán)限為多個(gè)角色對應(yīng)的資源疊加。如果擁有某個(gè)資源權(quán)限就返回?cái)?shù)據(jù),否則提示無權(quán)限。

        默認(rèn)如果沒有匹配任何資源,表示該資源無需特別權(quán)限,只需要登錄用戶即可。


        驗(yàn)證


        customerResource?添加客戶資源,ANT url為/api/business/customer/**,操作為*,表示GET,PATCH,DELETE,POST都需要授權(quán)。 如果操作為DELETE,表示值控制DELETE操作,其它操作不限制。

        noAuth?通過UI訪問客戶時(shí)候提示沒有權(quán)限,和期望的效果一致

        addRole?添加角色“客戶管理員”,該角色擁有客戶訪問權(quán)限

        addRoleLine?給“超級管理員”添加“客戶管理員”角色,這樣“超級管理員”就擁有了客戶訪問權(quán)限

        customerOK?因?yàn)橛脩糁匦路峙淞私巧枰枰N重新登錄,登錄之后又可以正常訪問客戶資源了。


        核心源碼


        @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);
        
                //獲取當(dāng)前訪問的路徑
                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));
                    }
                }
                // 未設(shè)置操作請求權(quán)限,返回空集合
                return configAttributes;
            }
        
            @Override
            public Collection<ConfigAttribute> getAllConfigAttributes() {
                return null;
            }
        
            @Override
            public boolean supports(Class<?> aClass) {
                return true;
            }
        
        }
        

        繼承FilterInvocationSecurityMetadataSource,實(shí)現(xiàn)getAttributes接口,通過http url加http method進(jìn)行匹配


        @Slf4j
        @Component
        public class DynamicAccessDecisionManager implements AccessDecisionManager {
        
            @Override
            public void decide(Authentication authentication, Object object,
                               Collection<ConfigAttribute> configAttributes) throws AccessDeniedException, InsufficientAuthenticationException {
                // 當(dāng)接口未被配置資源時(shí)直接放行
                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();
                    //將訪問所需資源或用戶擁有資源進(jìn)行比對
                    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) +"的訪問權(quán)限!");
            }
        
            @Override
            public boolean supports(ConfigAttribute configAttribute) {
                return true;
            }
        
            @Override
            public boolean supports(Class<?> aClass) {
                return true;
            }
        }
        

        繼承AccessDecisionManager,實(shí)現(xiàn)decide接口,將訪問所需資源或用戶擁有資源進(jìn)行比對,如果擁有權(quán)限則放行,否則提示無權(quán)限。


        小結(jié)


        本文介紹了RBAC在crudapi中的實(shí)現(xiàn)原理,首先引入Spring security框架,然后利用配置生成用戶,角色,資源等表單,通過配置實(shí)現(xiàn)基本的CRUD功能,最終實(shí)現(xiàn)了動(dòng)態(tài)權(quán)限精細(xì)化管理。因?yàn)橛脩?,角色等表與業(yè)務(wù)無關(guān),所以會(huì)作為系統(tǒng)內(nèi)置表單。


        附demo演示


        本系統(tǒng)屬于產(chǎn)品級的零代碼平臺,不同于自動(dòng)代碼生成器,不需要生成Controller、Service、Repository、Entity等業(yè)務(wù)代碼,程序運(yùn)行起來就可以使用,真正0代碼,可以覆蓋基本的和業(yè)務(wù)無關(guān)的CRUD RESTful API。

        官網(wǎng)地址:https://crudapi.cn(opens new window)


        測試地址:https://demo.crudapi.cn/crudapi/login(opens new window)




        瀏覽 62
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評論
        圖片
        表情
        推薦
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            国产日韩精品在线免费播放 | 亚洲观看黄 色 网 | 操逼网1234| 啪一啪国内在线视频 | 操比视频免费看 | 国产三页 | 欧美在线人| 麻豆猫爪-熊猫成人网 | 十八毛片| 极品国产在线 |