Shiro
入门案例
package com.liu;
import org.apache.shiro.SecurityUtils;
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;
public class TestAuthenticator {
public static void main(String[] args) {
//1、创建安全管理器对象
DefaultSecurityManager securityManager = new DefaultSecurityManager();
//2、给安全管理器设置realm
securityManager.setRealm(new IniRealm("classpath:shiro.ini"));
//3、SecurityUtils 给全局安全工具类设置安全管理器
SecurityUtils.setSecurityManager(securityManager);
//4、关键对象 subject 主体
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken("lisi","111");
//5、创建令牌
try{
System.out.println("认证状态"+subject.isAuthenticated());
subject.login(usernamePasswordToken);//用户认证
System.out.println("认证状态"+subject.isAuthenticated());
}catch (UnknownAccountException e){
e.printStackTrace();
System.out.println("账号不存在");
}catch (Exception e){
e.printStackTrace();
System.out.println("密码错误");
}
}
}
//IncorrectCredentialsException : 密码错误
//UnknownAccountException : 账号不存在
认证:
- 最终执行用户名比较 SimpleAccountRealm
doGetAuthenticationInfo 在这个方法完成用户名的校验
- 最终密码校验是在AuthenticationRealm中
assertCredentialsMatch 方法自动完成密码校验
如果要实现切换密数据库密码校验,可以自己实现SimpleAccountRealm接口.
自定义realm,替代ini文件,作为密码源
自定义realm实现
/**
* 自定义realm实现 将认证/授权数据的来源转为数据库的实现
*/
public class CustomRealm extends AuthorizingRealm {
//授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
return null;
}
//认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//在token中获取用户名
String principal = (String) authenticationToken.getPrincipal();
System.out.println(principal);
//根据身份信息使用jddc mybatis查询相关数据库
if ("liu".equals(principal)){
//参数1 返回数据库正确用户名
//参数2 返回数据库中正确的密码
//参数3 提供当前realm的名字
SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo("xiaochen","1223",this.getName());
return simpleAuthenticationInfo;
}
return null;
}
}
测试自定义realm
public class TestCustomAuthenticator {
public static void main(String[] args) {
DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
//设置自定义realm
defaultSecurityManager.setRealm(new CustomRealm());
//将安全工具类设置安全管理器
SecurityUtils.setSecurityManager(defaultSecurityManager);
//通过安全工具类获取Subject
Subject subject = SecurityUtils.getSubject();
//创建token
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken("liu","123");
try {
subject.login(usernamePasswordToken);
System.out.println("验证"+subject.isAuthenticated());
}catch (Exception e){
System.out.println("密码");
e.printStackTrace();
}
}
}
MD5 算法+salt
MD5:一般用来加密或者签名(校验盒)
特点:算法不可逆,只能根据明文生成密文,而不能通过密文反推明文
如果内容相同,无论执行多少次md5生成结果始终一致.
密码在持久化之前,在service中,进行md5加密处理。由于可以使用穷举算法,反推出简单密码。
所以可以给密码加盐,再进行md5加密。
之后需要进行密码校验时,再用 用户输入的密码+盐 进行MD5加密,再和数据库存储的密码进行校验