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


一.使用的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的基本登錄認證流程,如有不當之處還望大家多多指教。

 

 

 

 

 

 

 

 

 

 

 

 

 

 



 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM