自定義過濾器配置 Shiro 認證失敗返回 json 數據

来源:https://www.cnblogs.com/emanjusaka/archive/2023/10/27/page_11.html
-Advertisement-
Play Games

`Shiro`許可權框架認證失敗預設是重定向頁面的,這對於前後端分離的項目及其不友好,可能會造成請求404的問題。現在我們自定義過濾器實現認證失敗返回json數據。 ...


by emanjusaka from ​ https://www.emanjusaka.top/archives/11 彼岸花開可奈何
本文歡迎分享與聚合,全文轉載請留下原文地址。

Shiro許可權框架認證失敗預設是重定向頁面的,這對於前後端分離的項目及其不友好,可能會造成請求404的問題。現在我們自定義過濾器實現認證失敗返回json數據。

攔截器就是一道道的關卡,每一道關卡都有各自的職責。

實現思路

由於Shiro預設的過濾器認證失敗後是進行重定向操作的,所以我們考慮自定義過濾器重寫它的邏輯。

  1. 設置 ShiroShiroFilterFactoryBean攔截請求進行認證並配置自定義的攔截器。

  2. 實現自定義的攔截器,重寫認證失敗後的邏輯。

實現過程

  1. 配置 ShiroShiroFilterFactoryBean設置攔截請求進行認證

    @Bean
        public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
            ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
            shiroFilterFactoryBean.setSecurityManager(securityManager);
            Map<String, String> map = new LinkedHashMap<>();
            //登出
            map.put("/logout", "logout");
            // 登錄
            map.put("/login","anon");
            //對所有用戶認證
            map.put("/**", "authc");
            Map<String, Filter> filterMap = new HashMap<>();
            // 自定義的攔截器
            filterMap.put("authc",new ShiroLoginFilter());
            shiroFilterFactoryBean.setFilters(filterMap);
            shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
            return shiroFilterFactoryBean;
        }
    

上面配置對登錄介面進行了放行,對其他介面都要進行認證,這個可以根據自己的實際需要去配置。同時還要配置我們的自定義攔截器,攔截器Map 的key要和配置的認證authc一致,否則會不生效。

  1. 實現自定義的攔截器,重寫認證失敗後的邏輯。

    package com.icms.shiro.filter;
    
    import com.alibaba.fastjson.JSON;
    import com.icms.enu.ExceptionCodeEnum;
    import com.icms.exception.CustomException;
    import com.icms.page.Result;
    import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
    import org.camunda.bpm.model.bpmn.impl.instance.From;
    
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.PrintWriter;
    
    /**
     * @Author emanjusaka
     * @Date 2023/10/25 14:42
     * @Version 1.0
     */
    public class ShiroLoginFilter extends FormAuthenticationFilter {
        @Override
        protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
            HttpServletResponse httpResponse = (HttpServletResponse) response;
            HttpServletRequest httpRequest = (HttpServletRequest) request;
            httpResponse.setStatus(200);
            httpResponse.setContentType("application/json;charset=utf-8");
            //解決跨域問題
            if ("OPTIONS".equals(httpRequest.getMethod())){
                httpResponse.setStatus(HttpServletResponse.SC_NO_CONTENT);;
                return true;
            }
            httpResponse.getWriter().print(JSON.toJSONString(new Result(ExceptionCodeEnum.STATUS_CODE_NO_LOGIN)));
            httpResponse.getWriter().flush();
            httpResponse.getWriter().close();
            return false;
        }
    }
    
    

    這裡自定義攔截器繼承FormAuthenticationFilter 重寫了 onAccessDenied 方法。在onAccessDenied 方法中我們可以返回我們需要的 json 數據,也可以記錄日誌執行我們自己的方法。這裡返回的數據是我自定義的Result 類,裡面包含了錯誤碼和錯誤信息。

    認證失敗是我們的業務邏輯的錯誤而不是網路請求的錯誤,所以我們把HTTP的狀態碼設置成了 200 ,通過我們自己定義的Result來返回實際的錯誤信息。

    註意:Shiro本身是沒有解決跨域問題的,我們要自己實現解決Shiro的跨域問題。

    例如/user/getUserInfo介面,沒有配置過濾,就會被攔截,這個時候無論是在Controller上還是在介面實現上配置@CrossOrigin,都不會生效。這個時候需要做如下配置:

    //解決跨域問題
            if ("OPTIONS".equals(httpRequest.getMethod())){
                httpResponse.setStatus(HttpServletResponse.SC_NO_CONTENT);
                return true;
            }
    

    自己實現攔截器設置允許跨域也是可以的,這裡使用的上述的方法。

擴展知識

Shiro中的攔截器

  1. authc攔截器:主要用於實現基於表單的身份驗證,它會攔截用戶登錄表單提交的路徑,併在攔截器工廠中配置該路徑。此外,它負責創建登錄認證所需的Token令牌,並觸發登錄認證流程。如果用戶已經登錄,那麼將直接進入要訪問的路徑;如果用戶未登錄,則訪問會被拒絕,並自動跳轉到登錄頁面。

  2. authcBasic攔截器:主要用於實現基於HTTP基本認證的身份驗證。

  3. logout攔截器:主要用於處理用戶的註銷請求。

  4. user攔截器:充當了整個安全管理器的入口,主要負責攔截需要安全控制的請求併進行處理。

  5. anon攔截器:這種攔截器允許不需要登錄就能訪問的資源,通常用於靜態資源或者移動端介面。

  6. roles攔截器:主要負責用戶的角色校驗。

  7. perms攔截器和roles攔截器:這兩個攔截器主要與授權相關,用於處理用戶角色和許可權相關的請求。

  8. port攔截器:它主要攔截網路請求,驗證用戶是否具有訪問特定埠的許可權。

  9. rest攔截器:用於在Web應用程式中對HTTP請求的請求方法(HTTP method)進行許可權過濾和控制。它的作用是限制用戶對某些HTTP請求方法的訪問許可權,例如GET、POST、PUT、DELETE等。通過該過濾器,您可以根據需要來控制某些請求方法的訪問許可權,並且可以根據不同的請求方法,對不同的用戶或用戶組進行特定的授權設置。

  10. ssl攔截器:主要用於處理SSL協議相關的請求。

  11. noSessionCreation攔截器:用於處理無狀態會話的過濾器。

public enum DefaultFilter{
  anno(AnonymousFilter.class),
  authc(FormAuthenticationFilter.class),
  authcBasic(BasicHttpAuthenticationFilter.class),
  logout(LogoutFilter.class),
  noSessionCreation(NoSessionCreationFilter.class),
  perms(PermissionsAuthorizationFilter.class),
  port(PortFilter.class),
  rest(HttpMethodPermissionFilter.class),
  roles(RolesAuthorizationFilter.class),
  ssl(SslFilter.class),
  user(UserFilter.class);
}

與身份驗證相關的攔截器

  • authc(FormAuthenticationFilter)

    基於表單的攔截器;如“/**=authc”,如果沒有登錄會跳轉到相應的登錄頁面登錄。
    主要屬性:
    usernameParam:表單提交的用戶名參數名(username)。
    passwordParam:表單提交的密碼參數名(password)。
    rememberMeParam:表單提交的記住我參數名(rememberMe)。
    loginUrl:登錄頁面地址(/login.jsp)。
    successUrl:登錄成功後的預設重定向地址。
    failureKeyAttribute:登錄失敗後錯誤信息存儲Key(shiroLoginFailure)。

  • authcBasic(BasicHttpAuthenticationFilter)

    Basic HTTP身份驗證攔截器,主要屬性:
    applicationName:彈出登錄框顯示的信息(application)。

  • logout(LogoutFilter)

    退出攔截器,主要屬性:
    redirectUrl:退出成功後重定向的地址(/)。
    示例:“/logout=logout”

  • user(UserFilter)

    用戶攔截器,用戶已經身份驗證/記住我登錄的都可。
    示例:“/**=user”

  • anon(AnnonymousFilter)

    匿名攔截器,即不需要登錄即可訪問,一般用於靜態資源過濾或者需要在登錄之前進行的請求。
    示例:“/static/**=anon”

與授權相關的攔截器

  • roles(RolesAuthorizationFilter)

    角色授權攔截器,驗證用戶是否擁有所有角色。主要屬性:
    loginUrl:登錄頁面地址(/login.jsp)。
    unauthorizedUrl:未授權後重定向的地址。
    示例:“/admin/**=roles[admin]”

  • perms(PermissionsAuthorizationFilter)

    許可權授權攔截器,驗證用戶是否擁有所有許可權,屬性和roles一樣。
    示例:“/user/**=perms[“user:create”]”

  • port(PortFilter)

    埠攔截器,主要屬性:
    port(80):可以通過的埠。
    示例:“/test=port[80]”,如果用戶訪問該頁面是非80埠,將自動將埠改為80並重定向到該80埠,其他路徑/參數等都一樣。

  • rest(HttpMethodPermissionFilter)

    rest風格攔截器,自動根據請求方法構建許可權字元串(GET=read,POST=create,PUT=update,DELETE=delete,HEAD=read,TRACE=read,OPTIONS=read,MKCOL=create)構建許可權字元串。
    示例:“/users=rest[user]”,會自動拼出“user:read,user:create,user:update,user:delete”許可權字元串進行許可權匹配(所有都得匹配,isPermittedAll)。

  • ssl(SslFilter)

    SSL攔截器,只有請求協議是https才能通過,否則自動跳轉到https埠(443),其他和port攔截器一樣。

其他攔截器

  • noSessionCreation(NoSessionCreationFilter)

    不創建會話攔截器,調用subject.getSession(false)不會有問題,但是如果subject.getSession(true)將拋出異常。

本文原創,才疏學淺,如有紕漏,歡迎指正。如果本文對您有所幫助,歡迎點贊,並期待您的反饋交流,共同成長。
原文地址: https://www.emanjusaka.top/archives/11
微信公眾號:emanjusaka的編程棧


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

-Advertisement-
Play Games
更多相關文章
  • 本章節主要講的是如何配置熱載入,會碰到什麼問題,要怎麼處理。`wmproxy`是由`Rust`編寫,已實現`http/https`代理,`socks5`代理, 反向代理,靜態文件伺服器,內網穿透,配置熱更新等, ...
  • 字元串中的BKDRHash哈希函數 在電腦科學中,哈希函數是一種將任意長度的輸入(也稱為“消息”)通過散列演算法轉換成固定長度的輸出,該輸出就是哈希值。哈希函數的一個重要特性是,對於相同的輸入,無論何時執行哈希函數,它都應該產生相同的輸出。然而,對於不同的輸入,即使它們只有微小的差別,哈希函數也應該 ...
  • 本文分享自華為雲社區《深入理解Java中的Reader類:一步步剖析》,作者:bug菌。 前言 在Java開發過程中,我們經常需要讀取文件中的數據,而數據的讀取需要一個合適的類進行處理。Java的IO包提供了許多類用於數據的讀取和寫入,其中Reader便是其中之一。本文將對Java中的Reader進 ...
  • 這是做什麼用的 框架用途 在採集大量新聞網站時,不可避免的遇到動態載入的網站,這給配模版的人增加了很大難度。本來配靜態網站只需要兩個技能點:xpath和正則,如果是動態網站的還得抓包,遇到加密的還得js逆向。 所以就需要用瀏覽器渲染這些動態網站,來減少了配模板的工作難度和技能要求。動態載入的網站在新 ...
  • Hutool它是一個Java工具集類庫,包含了很多靜態方法的封裝:流處理、時間日期處理、正則處理、加解密處理、文件處理、集合處理等,可以說是項目中幾乎所有XxxxUtil的替代品,它可以使你更多的關註代碼邏輯,優雅的寫出高效代碼,避免“複製粘貼,改改再戰”。 ...
  • 函數 (1)函數的定義 函數使用func進行定義 函數是基本的代碼塊,用於執行一個任務 Go語言至少有一個main函數 函數聲明告訴了編譯器函數的名稱,返回類型和參數 //1.無參數無返回值函數的定義 func test1(){ fmt.Println("無參數無返回值函數的定義\n") } //2 ...
  • 作者:hinotoyk 鏈接:https://juejin.cn/post/6910215219822362632 背景:某日在公司中擼代碼的時候,在一個常用的controller中添加一個方法,測試時突然報錯說註入的service為null,搗鼓一陣發現後是方法修飾符寫成private,修改成pu ...
  • BeautifulSoup庫用於從HTML或XML文件中提取數據。它可以自動將複雜的HTML文檔轉換為樹形結構,並提供簡單的方法來搜索文檔中的節點,使得我們可以輕鬆地遍歷和修改HTML文檔的內容。廣泛用於Web爬蟲和數據抽取應用程式中。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...