再見了 Shiro!

来源:https://www.cnblogs.com/javastack/archive/2023/08/31/17669537.html
-Advertisement-
Play Games

## 1、前言 作為一名後臺開發人員,許可權這個名詞應該算是特別熟悉的了。就算是java里的類也有 public、private 等“許可權”之分。之前項目里一直使用shiro作為許可權管理的框架。說實話,shiro的確挺強大的,但是它也有很多不好的地方。shiro預設的登錄地址還是login.jsp,前 ...


1、前言

作為一名後臺開發人員,許可權這個名詞應該算是特別熟悉的了。就算是java里的類也有 public、private 等“許可權”之分。之前項目里一直使用shiro作為許可權管理的框架。說實話,shiro的確挺強大的,但是它也有很多不好的地方。shiro預設的登錄地址還是login.jsp,前後端分離模式使用shiro還要重寫好多類;手機端存儲用戶信息、保持登錄狀態等等,對shiro來說也是一個難題。

在分散式項目里,比如電商項目,其實不太需要明確的許可權劃分,說白了,我認為沒必要做太麻煩的許可權管理,一切從簡。何況shiro對於springCloud等各種分散式框架來說,簡直就是“災難”。每個子系統里都要寫點shiro的東西,慢慢的,越來越噁心。zuul網關就在這裡大顯身手了,控制用戶的登錄,鑒定用戶的許可權等等。zuul網關控制用戶登錄,鑒權以後再詳說。以上拙見。

然後最近我發現了另一個許可權框架jcasbin,雖然網上還沒有很多關於博客,但是我看了一會就可以使用了。

github地址:https://github.com/casbin/jcasbin

2、準備

Spring Boot 基礎就不介紹了,推薦看這個實戰項目:

https://github.com/javastacks/spring-boot-best-practice

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把用戶的角色、許可權信息(訪問路徑)放置在配置文件里,然後通過輸入流讀取配置文件。主要有兩個配置文件:model.conf 和 policy.csv。簡單的使用GitHub里都講了,在此就不再贅述了。

其實也可以讀取資料庫的角色許可權配置。所以我們可以把關於資料庫的信息提取出來,可以進行動態設置。

@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里進行相關配置了。model.conf是固定的文件,之間複製過來放在新建的和src同級的文件夾下即可。policy.csv的內容是可以從資料庫讀取的。

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

3、讀取許可權信息進行初始化

我們要對Enforcer這個類初始化,載入配置文件里的信息。所以我們寫一個類實現InitializingBean,在容器載入的時候就初始化這個類,方便後續的使用。

@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;
    //從資料庫讀取策略
    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.
  }
  
  /**
   * 添加許可權
   * @param policy
   * @return
   */
  public static boolean addPolicy(Policy policy){
    boolean addPolicy = enforcer.addPolicy(policy.getSub(),policy.getObj(),policy.getAct());
    enforcer.savePolicy();
    
    return addPolicy;
  }
  
  /**
   * 刪除許可權
   * @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;
  }
  
}

在這個類里,我們註入寫好的配置類,然後轉為靜態的,在afterPropertiesSet方法里實例化Enforcer並載入policy(策略,角色許可權/url對應關係)。

同時又寫了兩個方法,用來添加和刪除policy,Policy是自定的一個類,對官方使用的集合/數組進行了封裝。

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

4、使用

1、許可權控制

jcasbin的許可權控制非常簡單,自定義一個過濾器,if判斷就可以搞定,沒錯,就這麼簡單。

@WebFilter(urlPatterns = /* , filterName = JCasbinAuthzFilter)
@Order(Ordered.HIGHEST_PRECEDENCE)//執行順序,最高級別最先執行,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(無權訪問);
      Map<String, Object> result = new HashMap<String, Object>();
            result.put(code, 1001);
            result.put(msg, 用戶許可權不足);
            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)這個方法對用戶、訪問資源、方式進行匹配。這裡的邏輯可以根據自己的業務來實現。在這個過濾器之前還可以添加一個判斷用戶是否登錄的過濾器。

2、添加刪除許可權

對於許可權的操作,直接調用上面寫好的EnforcerFactory里對應的方法即可。並且,可以達到同步的效果。就是不用重啟伺服器或者其他任何操作,添加或刪除用戶許可權後,用戶對應的訪問就會收到影響。

@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();
  }

5、最後

其實可以把jcasbin和SpringCloud的zuul結合來實現用戶的統一登錄和許可權控制。自定義一個過濾器繼承ZuulFilter即可,其他地方基本沒啥區別。這個以後再寫。

版權聲明:本文為CSDN博主「紅藕香殘玉簟秋」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。原文鏈接:https://blog.csdn.net/WayneLee0809/article/details/85702551

近期熱文推薦:

1.1,000+ 道 Java面試題及答案整理(2022最新版)

2.勁爆!Java 協程要來了。。。

3.Spring Boot 2.x 教程,太全了!

4.別再寫滿屏的爆爆爆炸類了,試試裝飾器模式,這才是優雅的方式!!

5.《Java開發手冊(嵩山版)》最新發佈,速速下載!

覺得不錯,別忘了隨手點贊+轉發哦!


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Java - ThreadPoolExecutor源碼分析 1. 為什麼要自定義線程池 首先ThreadPoolExecutor中,一共提供了7個參數,每個參數都是非常核心的屬性,線上程池去執行任務時,每個參數都有決定性的作用。 但是如果直接採用JDK提供的方式去構建,可見設置的核心參數最多就兩個, ...
  • # Python的數據類型的內置方法 - 可變與不可變數據類型 - 字典的內置方法 - 元組的內置方法 - 集合的內置方法 ## 可變與不可變數據類型 ### 常見的數據類型 ```python 常見的數據結構類型:鏈表、單鏈表、雙鏈表、迴圈列表、(C實現的 指針)、棧、樹、二叉樹、平衡二叉樹、完全 ...
  • 由於瀏覽器可以迅速地解析JSON對象,它們有助於在客戶端和伺服器之間傳輸數據。本文將描述如何使用Python的JSON模塊來傳輸和接收JSON數據。 ### JavaScript Object Notation JSON (JavaScript Object Notation)是一種用於數據交換的語 ...
  • ### 拾取和解除拾取 對象的序列化是將對象轉換為比特形式的方法,這樣我們就可以在硬碟上保存對象的狀態。儘管許多語言都為我們提供了對象序列化的方式,但Python在所有的語言中更加靈活。 在Python中,對象序列化被稱為pickling,而去序列化被稱為unpickling。我們在 Python ...
  • 本節內容 列表、元組操作 字元串操作 字典操作 集合操作 文件操作 字元編碼與轉碼 1. 列表、元組操作 列表是我們最以後最常用的數據類型之一,通過列表可以對數據實現最方便的存儲、修改等操作 定義列表 names = ['Alex',"Tenglan",'Eric'] 通過下標訪問列表中的元素,下標 ...
  • 隨著互聯網的發展,越來越多的企業開始構建自己的API介面。而隨著API介面的增多,調用者需要瞭解API的參數和返回值,這時我們就需要一種方便快捷的查詢方式。本文將介紹一種以介面參數線上查詢為核心的方式,同時以銀行三要素驗證介面為例,展示如何實現介面參數線上查詢。 一、什麼是API介面 API(App ...
  • ## 常用經驗 - 在HTTP中,我們要通過 URL 進行資源的定位 >比如: > >要取 id=888 的用戶信息,我們就向/user/{id} 這個路徑發送請求, > >要取 id=888 的用戶的訂單列表,我們就向/user/{id}/orders 這個路徑發送請求 - 在HTTP 中,DEL ...
  • Excel是一種常用的電子錶格軟體,廣泛應用於金融、商業和教育等領域。它提供了強大的數據處理和分析功能,可進行各種計算和公式運算,並能創建各種類型的圖表和可視化數據。Excel的靈活性使其成為處理和管理數據的重要工具。本文將介紹如何使用 Spire.XLS for Python 通過代碼創建Exce ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...