菜鳥手把手學Shiro之shiro認證流程

来源:https://www.cnblogs.com/seanRay/archive/2019/11/11/11838875.html
-Advertisement-
Play Games

一.使用的spring boot +mybatis-plus+shiro+maven來搭建項目框架 1 <!--shiro--> 2 <dependency> 3 <groupId>org.apache.shiro</groupId> 4 <artifactId>shiro-core</artifa ...


一.使用的spring boot +mybatis-plus+shiro+maven來搭建項目框架

 1 <!--shiro-->
 2         <dependency>
 3             <groupId>org.apache.shiro</groupId>
 4             <artifactId>shiro-core</artifactId>
 5             <version>1.4.0</version>
 6         </dependency>
 7         <dependency>
 8             <groupId>org.apache.shiro</groupId>
 9             <artifactId>shiro-spring</artifactId>
10             <version>1.4.0</version>
11         </dependency>

2.寫一個登錄頁面(登錄頁面代碼就自己隨便寫一個form表單提交到controller就行)

3.在controller中創建userLogin方法,創建UsernamePasswordToken,獲取subject,通過subject.login來進行登錄認證。

 1 @Slf4j
 2 @RestController
 3 @RequestMapping("/sys-user")
 4 public class SysUserController {
 5 
 6     /**
 7      * 用戶登錄
 8      * @param userName
 9      * @param password
10      */
11     @PostMapping(value = "/login")
12     public ServerResponse userLogin(@RequestParam String userName, @RequestParam String password)
13     {
14         //1.獲取token
15         UsernamePasswordToken token = new UsernamePasswordToken(userName,password);
16         //2.獲取subject
17         Subject subject = SecurityUtils.getSubject();
18         //3.進行登錄
19         try {
20             subject.login(token);
21             log.info("subject:"+subject.getPrincipal().toString());
22             return ServerResponse.createBySuccessMessage("登錄成功!");
23         }catch (Exception e)
24         {
25             log.error("登錄失敗,用戶名[{}]", userName, e);
26             token.clear();
27             return ServerResponse.createByErrorMessage(e.getMessage());
28         }
29     }

以上就是一個基本的登錄流程,下麵就繼續分析subject.login()方法,到底怎麼實現登錄認證的,在後續中逐步分析如何使用自定義的Realm和CredentialsMatcher密碼比較器.

首先,我們從外部來看 Shiro 吧,即從應用程式角度的來觀察如何使用 Shiro 完成工作。如下圖:(引用自《跟我學shiro教程》)

4.通過代碼跟蹤可以發現,subject.login()方法又調用了securityManager.login()方法,因此我們還需要一個註冊一個securityManager的bean交給spring去管理

5.創建一個config的package,便於管理,項目結構如下

6.創建一個ShiroConfig的類,用來配置shiro相關的bean,首先使用@Configuration註解表明這是一個配置類,並註冊一個securityManager的bean,發現傳入參數是一個MyRealm的類,這個類就是我們需要自己去定義的Realm類

 1  //配置核心安全事務管理器
 2     /**
 3      * securityManager
 4      * @param authRealm ,@Qualifier表明瞭哪個實現類才是我們所需要的
 5      * @return
 6      */
 7     @Bean(name="securityManager")
 8     public SecurityManager securityManager(@Qualifier("myRealm") MyRealm authRealm) {
 9 
10         DefaultSecurityManager securityManager = new DefaultWebSecurityManager();
11 
12         //設置Realm
13         securityManager.setRealm(authRealm);
14         securityManager.setRememberMeManager(rememberMeManager());
15         return securityManager;
16     }
17     //配置自定義的許可權登錄器
18     @Bean
19     public MyRealm myRealm()
20     {
21         MyRealm myRealm = new MyRealm();
22         myRealm.setCredentialsMatcher(new CredentialsMatcher());
23         return myRealm;
24     }

 7.創建類Realm類並繼承AuthorizingRealm類,然後通過token中的Principal(即用戶名)去查詢資料庫中User,然後再把查詢到的用戶信息(包括密碼)返回AuthorizationInfo

 自定義MyRealm類繼承thorizingRealm類,並且重寫doGetAuthenticationInfo方法

 1 public class    MyRealm extends AuthorizingRealm{
 2 
 3     @Autowired
 4     private SysUserServiceImpl sysUserService;
 5     //授權
 6     @Override
 7     protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
 8         return null;
 9     }
10 
11     //認證
12     @Override
13     protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
14         /**獲取用戶輸入的用戶信息*/
15         String userName = (String)token.getPrincipal();
16         QueryWrapper<SysUser> queryWrapper = new QueryWrapper<SysUser>();
17 
18 
19         queryWrapper.eq("username",userName);
20 
21         SysUser user = sysUserService.getOne(queryWrapper);
22 
23         if(user == null)
24         {
25             throw new UnknownAccountException("該用戶不存在");
26         }
27         if(user.getStatus() != null && Const.UserStatusEnum.DISABLE.getCode().equals(user.getStatus()))
28         {
29             throw  new LockedAccountException("該賬號被鎖定,請聯繫管理員!");
30         }
31         //把user信息放在session中
32         SecurityUtils.getSubject().getSession().setAttribute(Const.CURRENT_USER,user);
33         return new SimpleAuthenticationInfo(user,user.getPassword(), ByteSource.Util.bytes(userName),getName());
34     }
35 }

如果身份認證失敗就會捕獲AuthenticationException,常見的如下:

DisabledAccountException(禁用的帳號)

LockedAccountException(鎖定的帳號)

UnknownAccountException(錯誤的帳號)

ExcessiveAttemptsException(登錄失敗次數過多)

IncorrectCredentialsException (錯誤的憑證)

ExpiredCredentialsException(過期的憑證)等

如果身份認證通過後就要進行密碼認證

 

 

自定義一個CredentialsMatcher類繼承SimpleCredentialsMatcher類,並且重寫doCredentiaIsMatch方法

 

以上就是shiro的基本登錄認證流程,如有不當之處還望大家多多指教。

 

 

 

 

 

 

 

 

 

 

 

 

 

 



 


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

-Advertisement-
Play Games
更多相關文章
  • 一、貪婪和非貪婪 1.貪婪:儘可能多的匹配,(*)表示貪婪匹配 2.非貪婪:找到符合條件的最小內容即可,(?)表示非貪婪 3.正則預設使用貪婪匹配 import re title = u"<div>name</div><div>age</div>" p1 = re.compile(r"<div>.* ...
  • 很多伙伴對 Python 的迭代器、可迭代對象、生成器這幾個概念有點搞不清楚,我來說說我的理解,希望對需要的朋友有所幫助。 1 迭代器協議 迭代器協議是核心,搞懂了這個,上面的幾個概念也就很好理解了。 所謂迭代器協議,就是要求一個迭代器必須要實現如下兩個方法 Return the iterator ...
  • 分頁查詢在網頁中隨處可見,那原理是什麼呢?下麵簡單介紹一下基於MySql資料庫的limit實現方法。 首先明確為什麼要使用分頁查詢,因為數據龐大,查詢不可能全部顯示在頁面上,如果全部顯示在頁面上,也會造成查詢速度慢的情況,所以分頁查詢解決了①數據查詢;②性能優化,等(其他問題歡迎補充)的問題。 分頁 ...
  • 一次線上頻繁FullGC問題的排查和解決記錄,整理了一下通用的排查解決過程,同時介紹了一些可能會用到的工具。 ...
  • 場景 JavaSE基礎 面向對象特征以及理解 訪問許可權修飾符區別 理解clone對象 JavaSE語法 java有沒有goto語句 &和&&的區別 如何跳出當前的多重嵌套迴圈? 是否可以繼承String? 重載與重寫的區別? char型變數中能不能存儲一個中文漢字? 抽象類與介面的異同 抽象方法是否 ...
  • 本文收錄在Python從入門到精通系列文章系列 1. 分支結構 1.1 應用場景 迄今為止,我們寫的Python代碼都是一條一條語句順序執行,這種代碼結構通常稱之為順序結構。然而僅有順序結構並不能解決所有的問題,比如我們設計一個游戲,游戲第一關的通關條件是玩家獲得1000分,那麼在完成本局游戲後,我 ...
  • 重構的手法有很多種,相對而言,一篇文章的涵蓋量自然是無法提到所有,米兜這裡也只能提出一些平時會經常使用的一些手法,像一些比較高端的手法,各位有興趣的可以去找一些專門的書籍涉獵。 另外還有一點,由於米兜是做JAVA開發的,因此部分重構小技巧可能與JAVA語言,或者說與面向對象的語言息息相關,不過大多數 ...
  • 小明是一個很牛逼的程式員,在國際標準化組織工作。 他現在正在設計新一代的C++標準,標準中有一個待實現的函數:findMax(),這個函數要求使用者輸入任何類型的數據,他都能找到最大的一個。 於是他想到了這個: int findMax(int a,int b){ if(a>b){ return a; ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...