Shiro之自定义Principal和Realm
在Shiro中Realm相当于一个安全数据源,在Realm中提供的方法获取用户数据,进行匹配验证。
比如,当身份验证时会调用doGetAuthenticationInfo方法,而具体的匹配操作可在该方法内查询权限,并进行匹配。
如果使用shiro默认的密码匹配的话,通常会返回一个SimpleAuthenticationInfo的对象,SimpleAuthenticationInfo的其中一个构造方法如下:
public SimpleAuthenticationInfo(Object principal, Object credentials, String realmName) { this.principals = new SimplePrincipalCollection(principal, realmName); this.credentials = credentials; } public SimpleAuthenticationInfo(PrincipalCollection principals, Object credentials) { this.principals = new SimplePrincipalCollection(principals); this.credentials = credentials; }
通过构造方法可以看出,创建SimpleAuthenticationInfo对象时,构造参数中,有一个类型为Object的对象principal,或者PrincipalCollection类型的principals。
通过构造方法可以看出,principal为Object类型,也就是说可以是任何对象。那么也就可以自定义一个principal。
下面就尝试自定义一个principal对象,并看看如何使用。首先,自定义Principal:
public class Principal implements Serializable { /** * 姓名 */ private String name; /** * 手机号 */ private String mobile; public Principal(String name, String mobile) { this.name = name; this.mobile = mobile; } // 省略getter/setter }
然后自定义一个Realm,通过实现AuthorizingRealm:
public class PrincipalRealm extends AuthorizingRealm { @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { return null; } @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { String name = "tom"; String mobile = "156*********"; String password = "123456"; String salt = "abc"; System.out.println("进行认证..."); return new SimpleAuthenticationInfo(new Principal(name, mobile), password, ByteSource.Util.bytes(salt), getName()); } }
在doGetAuthenticationInfo方法中创建Principal对象,并返回。
下面看使用的实例:
@Test public void testAuthentication() { PrincipalRealm principalRealm = new PrincipalRealm(); // 1.构建SecurityManager环境 DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager(); defaultSecurityManager.setRealm(principalRealm); // 2.主体提交认证请求 // 设置SecurityManager环境 SecurityUtils.setSecurityManager(defaultSecurityManager); // 获取当前主体 Subject subject = SecurityUtils.getSubject(); UsernamePasswordToken token = new UsernamePasswordToken("Tom", "123456"); // 登录 subject.login(token); // 获取自定会的Principal Principal principal = (Principal) subject.getPrincipal(); System.out.println(principal.getMobile()); // subject.isAuthenticated()方法返回一个boolean值,用于判断用户是否认证成功 System.out.println("isAuthenticated:" + subject.isAuthenticated()); }
执行单元测试,会发现通过Subject可以获得到在Realm中存储的信息,并且对传入的参数进行了校验。当换一个新的用户名密码之后,在此执行,会抛出异常。
上述实例完整代码:https://github.com/secbr/shiro/blob/main/shiro-demo1/src/main/java/com/choupangxia/principal/PrincipalTest.java
关注公众号:程序新视界,一个让你软实力、硬技术同步提升的平台
除非注明,否则均为程序新视界原创文章,转载必须以链接形式标明本文链接
本文链接:http://choupangxia.com/2021/01/27/shiro-principal-realm/