一.分析
1.验证用户名
最终指向用户名比较是在SimpleAccountRealm类中,doGetAuthenticationInfo方法完成用户名校验。【需要重写方法,完成数据库校验】
2.验证密码
最终密码校验是在AuthenticatingRealm类中,assertCredentialsMatch方法完成校验。【自动校验】
二.总结
1.认证realm【继承AuthenticatingRealm类】
需要重写doGetAuthenticationInfo方法
2.授权realm【继承AuthorizingRealm类】
需要重写doGetAuthorizationInfo方法
三.范例一【测试工作流程】
1.代码块
package com.fengmo;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.text.IniRealm;
import org.apache.shiro.subject.Subject;
/**
* 测试shiro执行流程
*/
public class TestAuthenticator {
public static void main(String[] args) {
//1.创建安全管理器对象securityManager
DefaultSecurityManager securityManager = new DefaultSecurityManager();
//2.给安全管理器设置realm
securityManager.setRealm(new IniRealm("classpath:shiro.ini"));
//3.SecurityUtils 给全局安全工具类【框架自带】设置安全管理器
SecurityUtils.setSecurityManager(securityManager);
//4.获取当前主体的对象【访问用户】
Subject subject = SecurityUtils.getSubject();
//5.创建令牌【身份信息,凭证信息】
UsernamePasswordToken token = new UsernamePasswordToken("xiaochen","123");
try {
//6.用户认证
subject.login(token); //放置令牌
System.out.println("认证状态:"+ subject.isAuthenticated());
}catch (UnknownAccountException e){//认证失败则会发生异常
e.printStackTrace();
System.out.println("该异常是用户名不存在");
}catch (IncorrectCredentialsException e){
e.printStackTrace();
System.out.println("该异常是密码错误");
}
}
}
2.范例
四.范例二【测试自定义认证】
1.说明
MD5算法:
1.作用:一般用于加密或者签名(校验和)
2.特点:MD5算法不可逆,如何内容相同无论执行多少次md5生成结果始终是一致
3.生成结果:始终是一个16进制32位长度字符串
4.加密时选择MD5+Salt(盐)
2.自定义realm实现
(1)代码块
package com.relam;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
/**
* 自定义realm实现
* 将认证/获取数据的来源转为数据库的实现
*/
public class CustomerRealm extends AuthorizingRealm {
//这是授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
return null;
}
//这是认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//从token获取用户名
String principal = (String)token.getPrincipal();
// System.out.println(principal); //测试是否获取到身份信息
//总结:身份信息可以通过JDBC、Mybatis到数据库查询
//测试查询通过写法
if("xiaochen".equals(principal)){
//创建AuthenticationInfo的实现类
//参数为数据库中的用户名,密码,第三个参数为realm的名字
// SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo("xiaochen","123",this.getName());
//第二种写法:由于查询数据库靠principal对象,所以可以直接写成
SimpleAuthenticationInfo authenticationInfo2 = new SimpleAuthenticationInfo(principal,"123123",this.getName());
return authenticationInfo2;
}
return null;
}
}
(2)范例
3.测试类
(1)代码块
package com.fengmo;
import com.relam.CustomerRealm;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.subject.Subject;
/**
* 测试重写自定义认证
*/
public class TestAuthenticator2 {
public static void main(String[] args) {
//创建security Manager
DefaultSecurityManager securityManager = new DefaultSecurityManager();
//设置自定义realm
securityManager.setRealm(new CustomerRealm());
//将安全工具类设置安全管理器
SecurityUtils.setSecurityManager(securityManager);
//通过安全工具类获取subject
Subject subject = SecurityUtils.getSubject();
//创建令牌
UsernamePasswordToken token = new UsernamePasswordToken("xiaochen", "123123");
//认证
try{
//认证
subject.login(token); //这里调用自定义认证
System.out.println("验证认证结果"+subject.isAuthenticated());
}catch (UnknownAccountException e){ //用户名不存在
e.printStackTrace();
System.out.println("用户名错误");
}catch (IncorrectCredentialsException e2){ //密码错误
e2.printStackTrace();
System.out.println("密码错误");
}
}
}