<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

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

          共 5302字,需瀏覽 11分鐘

           ·

          2021-02-28 12:23

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

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


          概要


          RBAC簡介


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

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

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

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


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


          一個用戶有一個或多個角色

          一個角色包含多個用戶

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

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


          Spring security


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


          表單配置


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


          資源resource


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


          用戶user


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


          角色role


          role?角色


          用戶角色行userRoleLine


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


          角色資源行roleResourceLine


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


          表關(guān)系


          relation


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


          權(quán)限控制原理


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

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


          驗證


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

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

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

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

          customerOK?因為用戶重新分配了角色,需要需要注銷重新登錄,登錄之后又可以正常訪問客戶資源了。


          核心源碼


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

          繼承FilterInvocationSecurityMetadataSource,實現(xiàn)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) +"的訪問權(quán)限!");
              }
          
              @Override
              public boolean supports(ConfigAttribute configAttribute) {
                  return true;
              }
          
              @Override
              public boolean supports(Class<?> aClass) {
                  return true;
              }
          }
          

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


          小結(jié)


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


          附demo演示


          本系統(tǒng)屬于產(chǎn)品級的零代碼平臺,不同于自動代碼生成器,不需要生成Controller、Service、Repository、Entity等業(yè)務(wù)代碼,程序運行起來就可以使用,真正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
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  男女激情视频在线观看 | 日韩有码日韩无码 | 国产真实乱子伦偷精品! | 男女啪啪网站国产 | 亚洲无码AV电影 |