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

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

 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就行)github

3.在controller中建立userLogin方法,建立UsernamePasswordToken,獲取subject,經過subject.login來進行登陸認證。spring

 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教程》)apache

4.經過代碼跟蹤能夠發現,subject.login()方法又調用了securityManager.login()方法,所以咱們還須要一個註冊一個securityManager的bean交給spring去管理安全

5.建立一個config的package,便於管理,項目結構以下session

6.建立一個ShiroConfig的類,用來配置shiro相關的bean,首先使用@Configuration註解代表這是一個配置類,並註冊一個securityManager的bean,發現傳入參數是一個MyRealm的類,這個類就是咱們須要本身去定義的Realm類mybatis

 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,而後再把查詢到的用戶信息(包括密碼)返回AuthorizationInfoapp

 自定義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(過時的憑證)等

若是身份認證經過後就要進行密碼認證(未完待續),相關代碼會上傳到github上

相關文章
相關標籤/搜索