一、前言
上一篇中,我们直接去shiro.ini中去查找对应的账号和密码,直接将这些固定写死的数据加载到SecurityManager中。这种方式不灵活,正常的逻辑应该允许我们去数据库中查找某个用户是否存在。再获取用户信息,做密码校验。我们可以通过自定义的Realm方式,完成这种功能。
二、 自定义Realm的步骤
2.1. 写一个类MyRealm继承 AuthorizingReaml
并重写以下三个方法
getName()
用于获取自定义reaml的名字doGetAuthorizationInfo(PrincipalCollection principals)
获取授权信息doGetAuthenticationInfo(AuthenticationToken token)
获取登录认证信息,其中token就是用户传进来的账号信息,Authoricator
授权器根据返回的AuthenticationInfo信息来和用户输入的数据对比,再做相应的判断(比如抛出异常)。
/**
* 自定义reaml
*/
public class MyReaml extends AuthorizingRealm {
@Override
//返回自定义Reaml的名字
public String getName() {
return "MyReaml";
}
//获取授权信息的功能
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
return null;
}
//获取登录认证信息的功能
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//获取传进来的用户账号
String username = (String)token.getPrincipal();
System.out.println("username:"+username);
//模拟数据库中取出的账号信息
String username_db = "luohaizhang";
String password_db = "12345";
//假设数据库中不存在用户输入的username值,说明登录认证信息为空,也不需要继续做密码认证了,直接返回null
if(!username_db.equals(username)){
return null;
}
//否则就封装输入的账号和数据库中查询出的密码,返回AuthenticationInfo对象给Authoricator权限校验器校验。
return new SimpleAuthenticationInfo(username,password_db,getName());
}
}
2.2 定义shiro-reaml.ini文件
#自定义realm
myRealm = 自定义reaml的路径
#指定securityManager的realms实现
securityManager.realms=$myRealm
- 加载配置文件shiro-reaml.ini的配置文件
@Test
public void testForShiro02(){
//生成SecurityManager的工厂,加载shiro.ini中的配置。
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro-realm.ini");
SecurityManager instance = factory.getInstance();
//保存一个SecurityManager ,使得全局可以引用。
SecurityUtils.setSecurityManager(instance);
Subject subject = SecurityUtils.getSubject();
try {
//模拟用户名和密码
AuthenticationToken authenticationToken = new UsernamePasswordToken("luohaizhang", "12345");
//模拟用户登录,会去shiro.ini中对比
subject.login(authenticationToken);
}
catch (UnknownAccountException e){
System.out.println(e.getMessage());
System.out.println("找不到账号");
}
catch (IncorrectCredentialsException e){
System.out.println(e.getMessage());
System.out.println("密码错误");
}
//查看是否登录成功
System.out.println("用户登入后是否存在授权:" + subject.isAuthenticated());
//用户登出
subject.logout();
System.out.println("用户登出后,是否存在授权:" + subject.isAuthenticated());
}
使用自定义reaml的方式,就可以更加合理的校验用户的信息。