<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>

          更輕量級的權(quán)限管理框架:jcasbin

          共 8163字,需瀏覽 17分鐘

           ·

          2023-01-21 03:33

          大家好,我是寶哥

          前言

          作為一名后臺開發(fā)人員,權(quán)限這個(gè)名詞應(yīng)該算是特別熟悉的了。就算是java里的類也有 public、private 等“權(quán)限”之分。之前項(xiàng)目里一直使用shiro作為權(quán)限管理的框架。說實(shí)話,shiro的確挺強(qiáng)大的,但是它也有很多不好的地方。shiro默認(rèn)的登錄地址還是login.jsp,前后端分離模式使用shiro還要重寫好多類;手機(jī)端存儲(chǔ)用戶信息、保持登錄狀態(tài)等等,對shiro來說也是一個(gè)難題。

          在分布式項(xiàng)目里,比如電商項(xiàng)目,其實(shí)不太需要明確的權(quán)限劃分,說白了,我認(rèn)為沒必要做太麻煩的權(quán)限管理,一切從簡。何況shiro對于springCloud等各種分布式框架來說,簡直就是“災(zāi)難”。每個(gè)子系統(tǒng)里都要寫點(diǎn)shiro的東西,慢慢的,越來越惡心。zuul網(wǎng)關(guān)就在這里大顯身手了,控制用戶的登錄,鑒定用戶的權(quán)限等等。zuul網(wǎng)關(guān)控制用戶登錄,鑒權(quán)以后再詳說。以上拙見。

          然后最近我發(fā)現(xiàn)了另一個(gè)權(quán)限框架jcasbin,雖然網(wǎng)上還沒有很多關(guān)于博客,但是我看了一會(huì)就可以使用了。

          ?

          順手貼上github地址:https://github.com/casbin/jcasbin

          ?

          一、準(zhǔn)備

          基于springboot1.5.10,但是和springboot關(guān)系不太大。

          1、mavan倉庫引入

                
                <dependency>
          ????<groupId>org.casbin</groupId>
          ????<artifactId>jcasbin</artifactId>
          ????<version>1.1.0</version>
          </dependency>
          <dependency>
          ????<groupId>org.casbin</groupId>
          ????<artifactId>jdbc-adapter</artifactId>
          ????<version>1.1.0</version>
          </dependency>

          2、配置文件

          jcasbin把用戶的角色、權(quán)限信息(訪問路徑)放置在配置文件里,然后通過輸入流讀取配置文件。主要有兩個(gè)配置文件:model.confpolicy.csv。簡單的使用GitHub里都講了,在此就不再贅述了。

          其實(shí)也可以讀取數(shù)據(jù)庫的角色權(quán)限配置。所以我們可以把關(guān)于數(shù)據(jù)庫的信息提取出來,可以進(jìn)行動(dòng)態(tài)設(shè)置。

                
                @Configuration
          @ConfigurationProperties(prefix?=?"org.jcasbin")
          public?class?EnforcerConfigProperties?{
          ?
          ?private?String?url;
          ?
          ?private?String?driverClassName;
          ?
          ?private?String?username;
          ?
          ?private?String?password;
          ?
          ?private?String?modelPath;
          ?
          ?public?String?getUrl()?{
          ??return?url;
          ?}
          ?
          ?public?void?setUrl(String?url)?{
          ??this.url?=?url;
          ?}
          ?
          ?public?String?getDriverClassName()?{
          ??return?driverClassName;
          ?}
          ?
          ?public?void?setDriverClassName(String?driverClassName)?{
          ??this.driverClassName?=?driverClassName;
          ?}
          ?
          ?public?String?getUsername()?{
          ??return?username;
          ?}
          ?
          ?public?void?setUsername(String?username)?{
          ??this.username?=?username;
          ?}
          ?
          ?public?String?getPassword()?{
          ??return?password;
          ?}
          ?
          ?public?void?setPassword(String?password)?{
          ??this.password?=?password;
          ?}
          ?
          ?public?String?getModelPath()?{
          ??return?modelPath;
          ?}
          ?
          ?public?void?setModelPath(String?modelPath)?{
          ??this.modelPath?=?modelPath;
          ?}
          ?
          ?@Override
          ?public?String?toString()?{
          ??return?"EnforcerConfigProperties?[url="?+?url?+?",?driverClassName="?+?driverClassName?+?",?username="
          ????+?username?+?",?password="?+?password?+?",?modelPath="?+?modelPath?+?"]";
          ?}
          ?
          }

          這樣我們就可以在application.properties里進(jìn)行相關(guān)配置了。model.conf是固定的文件,之間復(fù)制過來放在新建的和src同級的文件夾下即可。policy.csv的內(nèi)容是可以從數(shù)據(jù)庫讀取的。

                
                org.jcasbin.url=jdbc:mysql://localhost:3306/casbin?useSSL=false
          org.jcasbin.driver-class-name=com.mysql.jdbc.Driver
          org.jcasbin.username=root
          org.jcasbin.password=root
          org.jcasbin.model-path=conf/authz_model.conf

          二、讀取權(quán)限信息進(jìn)行初始化

          我們要對Enforcer這個(gè)類初始化,加載配置文件里的信息。所以我們寫一個(gè)類實(shí)現(xiàn)InitializingBean,在容器加載的時(shí)候就初始化這個(gè)類,方便后續(xù)的使用。

                
                @Component
          public?class?EnforcerFactory?implements?InitializingBean?{
          ?
          ?private?static?Enforcer?enforcer;
          ?
          ?@Autowired
          ?private?EnforcerConfigProperties?enforcerConfigProperties;
          ?private?static?EnforcerConfigProperties?config;
          ?
          ?@Override
          ?public?void?afterPropertiesSet()?throws?Exception?{
          ??config?=?enforcerConfigProperties;
          ??//從數(shù)據(jù)庫讀取策略
          ??JDBCAdapter?jdbcAdapter?=?new?JDBCAdapter(config.getDriverClassName(),config.getUrl(),config.getUsername(),
          ?????????????config.getPassword(),?true);
          ??enforcer?=?new?Enforcer(config.getModelPath(),?jdbcAdapter);
          ??enforcer.loadPolicy();//Load?the?policy?from?DB.
          ?}
          ?
          ?/**
          ??*?添加權(quán)限
          ??*?@param?policy
          ??*?@return
          ??*/

          ?public?static?boolean?addPolicy(Policy?policy){
          ??boolean?addPolicy?=?enforcer.addPolicy(policy.getSub(),policy.getObj(),policy.getAct());
          ??enforcer.savePolicy();
          ??
          ??return?addPolicy;
          ?}
          ?
          ?/**
          ??*?刪除權(quán)限
          ??*?@param?policy
          ??*?@return
          ??*/

          ?public?static?boolean?removePolicy(Policy?policy){
          ??boolean?removePolicy?=?enforcer.removePolicy(policy.getSub(),policy.getObj(),policy.getAct());
          ??enforcer.savePolicy();
          ??
          ??return?removePolicy;
          ?}
          ?
          ?public?static?Enforcer?getEnforcer(){
          ??return?enforcer;
          ?}
          ?
          ?
          }

          在這個(gè)類里,我們注入寫好的配置類,然后轉(zhuǎn)為靜態(tài)的,在afterPropertiesSet方法里實(shí)例化Enforcer并加載policy(策略,角色權(quán)限/url對應(yīng)關(guān)系)。

          同時(shí)又寫了兩個(gè)方法,用來添加和刪除policy,Policy是自定的一個(gè)類,對官方使用的集合/數(shù)組進(jìn)行了封裝。

                
                public?class?Policy?{
          ?/**想要訪問資源的用戶?或者角色*/
          ?private?String?sub;
          ?
          ?/**將要訪問的資源,可以使用??*?作為通配符,例如/user/*?*/
          ?private?String?obj;
          ?
          ?/**用戶對資源執(zhí)行的操作。HTTP方法,GET、POST、PUT、DELETE等,可以使用?*?作為通配符*/
          ?private?String?act;
          ?
          ?public?Policy()?{
          ??super();
          ?}
          ?
          ?/**
          ??*?
          ??*?@param?sub?想要訪問資源的用戶?或者角色
          ??*?@param?obj?將要訪問的資源,可以使用??*?作為通配符,例如/user/*
          ??*?@param?act 用戶對資源執(zhí)行的操作。HTTP方法,GET、POST、PUT、DELETE等,可以使用?*?作為通配符
          ??*/

          ?public?Policy(String?sub,?String?obj,?String?act)?{
          ??super();
          ??this.sub?=?sub;
          ??this.obj?=?obj;
          ??this.act?=?act;
          ?}
          ?
          ?public?String?getSub()?{
          ??return?sub;
          ?}
          ?
          ?public?void?setSub(String?sub)?{
          ??this.sub?=?sub;
          ?}
          ?
          ?public?String?getObj()?{
          ??return?obj;
          ?}
          ?
          ?public?void?setObj(String?obj)?{
          ??this.obj?=?obj;
          ?}
          ?
          ?public?String?getAct()?{
          ??return?act;
          ?}
          ?
          ?public?void?setAct(String?act)?{
          ??this.act?=?act;
          ?}
          ?
          ?@Override
          ?public?String?toString()?{
          ??return?"Policy?[sub="?+?sub?+?",?obj="?+?obj?+?",?act="?+?act?+?"]";
          ?}
          ?
          }

          三、使用

          1、權(quán)限控制

          jcasbin的權(quán)限控制非常簡單,自定義一個(gè)過濾器,if判斷就可以搞定,沒錯(cuò),就這么簡單。

                
                @WebFilter(urlPatterns?=?"/*"?,?filterName?=?"JCasbinAuthzFilter")
          @Order(Ordered.HIGHEST_PRECEDENCE)//執(zhí)行順序,最高級別最先執(zhí)行,int從小到大
          public?class?JCasbinAuthzFilter?implements?Filter?{
          ?
          ?private?static?final?Logger?log?=?LoggerFactory.getLogger(JCasbinAuthzFilter.class);
          ?
          ?private?static?Enforcer?enforcer;
          ?
          ?@Override
          ?public?void?init(FilterConfig?filterConfig)?throws?ServletException?{
          ?}
          ?
          ?@Override
          ?public?void?doFilter(ServletRequest?servletRequest,?ServletResponse?servletResponse,?FilterChain?chain)
          ???throws?IOException,?ServletException?
          {
          ??HttpServletRequest?request?=?(HttpServletRequest)?servletRequest;
          ????????HttpServletResponse?response?=?(HttpServletResponse)?servletResponse;
          ????????
          ????????String?user?=?request.getParameter("username");
          ????????String?path?=?request.getRequestURI();
          ????????String?method?=?request.getMethod();
          ?
          ????????enforcer?=?EnforcerFactory.getEnforcer();
          ????????if?(path.contains("anon"))?{
          ?????????chain.doFilter(request,?response);
          ??}else?if?(enforcer.enforce(user,?path,?method))?{
          ???chain.doFilter(request,?response);
          ??}?else?{
          ???log.info("無權(quán)訪問");
          ???Map<String,?Object>?result?=?new?HashMap<String,?Object>();
          ????????????result.put("code",?1001);
          ????????????result.put("msg",?"用戶權(quán)限不足");
          ????????????result.put("data",null);
          ????????????response.setCharacterEncoding("UTF-8");
          ????????????response.setContentType("application/json");
          ????????????response.getWriter().write(JSONObject.toJSONString(result,SerializerFeature.WriteMapNullValue));
          ?????}
          ??
          ?}
          ?
          ?@Override
          ?public?void?destroy()?{
          ??
          ?}
          ?
          }

          主要是用enforcer.enforce(user, path, method)這個(gè)方法對用戶、訪問資源、方式進(jìn)行匹配。這里的邏輯可以根據(jù)自己的業(yè)務(wù)來實(shí)現(xiàn)。在這個(gè)過濾器之前還可以添加一個(gè)判斷用戶是否登錄的過濾器。

          2、添加刪除權(quán)限

          對于權(quán)限的操作,直接調(diào)用上面寫好的EnforcerFactory里對應(yīng)的方法即可。并且,可以達(dá)到同步的效果。就是不用重啟服務(wù)器或者其他任何操作,添加或刪除用戶權(quán)限后,用戶對應(yīng)的訪問就會(huì)收到影響。

                
                @PutMapping("/anon/role/per")
          public?ResultBO<Object>?addPer(){
          ?
          ?EnforcerFactory.addPolicy(new?Policy("alice",?"/user/list",?"*"));
          ?
          ?return?ResultTool.success();
          }

          @DeleteMapping("/anon/role/per")
          public?ResultBO<Object>?deletePer(){
          ?
          ?EnforcerFactory.removePolicy(new?Policy("alice",?"/user/list",?"*"));
          ?
          ?return?ResultTool.success();
          }

          寫在后面的話

          其實(shí)可以把jcasbin和SpringCloud的zuul結(jié)合來實(shí)現(xiàn)用戶的統(tǒng)一登錄和權(quán)限控制。自定義一個(gè)過濾器繼承ZuulFilter即可,其他地方基本沒啥區(qū)別。這個(gè)以后再寫。

          來源:blog.csdn.net/WayneLee0809/article/

          details/85702551

          往期推薦:

          300萬數(shù)據(jù)導(dǎo)入導(dǎo)出優(yōu)化方案,從80s優(yōu)化到8s(實(shí)測)

          SpringBoot+WebSocket實(shí)現(xiàn)服務(wù)端、客戶端

          別再使用 JWT 作為 Session 系統(tǒng)!問題重重且很危險(xiǎn)。

          2萬字系統(tǒng)總結(jié),幫你實(shí)現(xiàn) Linux 命令自由

          Controller 層代碼就該這么寫,簡潔又優(yōu)雅!

          推薦一個(gè)冷門又逆天的副業(yè)(Python兼職可月入10k+)

          Redis 官方可視化工具,高顏值,功能太強(qiáng)大!

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

          手機(jī)掃一掃分享

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

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <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>
                  A片在线视频 | 欧美性爱成人视频网站 | 91精品国际 | 大香aⅴ| 青青操免费 |