Apache Shiro 学习记录2

时间:2022-03-24 15:37:36

  写完上篇随笔以后(链接).....我也想自己尝试一下写一个Strategy.....Shiro自带了3个Strategy,教程(链接)里作者也给了2个.....我想写个都不一样的策略.....看来看去....决定写个LastSuccessfulStrategy好了...顾名思义就是返回最后一个Realm验证成功的AuthenticationInfo的信息...

 1 package com.github.zhangkaitao.shiro.chapter2.authenticator.strategy;
2
3 import org.apache.shiro.authc.AuthenticationException;
4 import org.apache.shiro.authc.AuthenticationInfo;
5 import org.apache.shiro.authc.AuthenticationToken;
6 import org.apache.shiro.authc.pam.AbstractAuthenticationStrategy;
7 import org.apache.shiro.realm.Realm;
8 import org.apache.shiro.util.CollectionUtils;
9
10 public class LastSuccessfulStrategy extends AbstractAuthenticationStrategy {
11 @Override
12 protected AuthenticationInfo merge(AuthenticationInfo info,
13 AuthenticationInfo aggregate) {
14 // TODO Auto-generated method stub
15 if (info != null && !CollectionUtils.isEmpty(info.getPrincipals()))
16 return info;
17 else
18 return aggregate;
19 }
20
21 @Override
22 public AuthenticationInfo afterAttempt(Realm realm,
23 AuthenticationToken token, AuthenticationInfo singleRealmInfo,
24 AuthenticationInfo aggregateInfo, Throwable t)
25 throws AuthenticationException {
26 // TODO Auto-generated method stub
27 return merge(singleRealmInfo, aggregateInfo);
28 }
29
30 @Override
31 public AuthenticationInfo afterAllAttempts(AuthenticationToken token, AuthenticationInfo aggregate) throws AuthenticationException {
32 //we know if one or more were able to succesfully authenticate if the aggregated account object does not
33 //contain null or empty data:
34 if (aggregate == null || CollectionUtils.isEmpty(aggregate.getPrincipals())) {
35 throw new AuthenticationException("Authentication token of type [" + token.getClass() + "] " +
36 "could not be authenticated by any configured realms. Please ensure that at least one realm can " +
37 "authenticate these tokens.");
38 }
39
40 return aggregate;
41 }
42 }

我的想法是这样的...只要Realm返回的info不为空,就把它作为aggregate储存起来...否则直接返回aggregate....所以我override了merge方法...并在afterAttemp里调用它....

然后所有Realm都处理完毕以后..如果aggregate是null...说明所有Realm都验证失败了...那么应该抛出异常....这里逻辑我就直接抄AtLeastOneSuccessfulStrategy类的代码了...

 

测试代码直接修改教程的就行了

 1     @Test
2 public void testHelloworld2() {
3 // 1、获取SecurityManager工厂,此处使用Ini配置文件初始化SecurityManager
4 Factory<org.apache.shiro.mgt.SecurityManager> factory = new IniSecurityManagerFactory(
5 "classpath:shiro2.ini");
6
7 // 2、得到SecurityManager实例 并绑定给SecurityUtils
8 org.apache.shiro.mgt.SecurityManager securityManager = factory
9 .getInstance();
10 SecurityUtils.setSecurityManager(securityManager);
11
12 // 3、得到Subject及创建用户名/密码身份验证Token(即用户身份/凭证)
13 Subject subject = SecurityUtils.getSubject();
14 UsernamePasswordToken token = new UsernamePasswordToken("zhang", "123");
15
16 try {
17 // 4、登录,即身份验证
18 subject.login(token);
19 }
20 catch (AuthenticationException e) {
21 // 5、身份验证失败
22 }
23
24 Assert.assertEquals(true, subject.isAuthenticated()); // 断言用户已经登录
25 System.out.println(subject.getPrincipal());
26
27 // 6、退出
28 subject.logout();
29 }

 

shiro2.ini也修改自教程

 1 [main]
2 #指定securityManager的authenticator实现
3 authenticator=org.apache.shiro.authc.pam.ModularRealmAuthenticator
4 securityManager.authenticator=$authenticator
5
6 #指定securityManager.authenticator的authenticationStrategy
7 lastSuccessfulStrategy=org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy
8 securityManager.authenticator.authenticationStrategy=$lastSuccessfulStrategy
9
10 myRealm1=com.github.zhangkaitao.shiro.chapter2.realm.MyRealm1
11 myRealm2=com.github.zhangkaitao.shiro.chapter2.realm.MyRealm2
12 myRealm3=com.github.zhangkaitao.shiro.chapter2.realm.MyRealm3
13 securityManager.realms=$myRealm1,$myRealm3,$myRealm2

 

3个Realm我就不贴了...和教程是一样的....

这样我自己的LastSuccessfulStrategy策略就完成啦O(∩_∩)O哈!