一些理论知识:
https://blog.csdn.net/zifengye520/article/details/121969099
一、基本使用
官网的入门案例,使用的是ini配置文件来模拟用户的信息,这里直接跳过这个步骤,直接使用自定义的Realm来模拟数据库获取用户信息
1、创建一个springboot项目
2、添加shiro依赖
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.5.3</version>
</dependency>
3、自定义Realm,继承AuthorizingRealm,模拟从数据库卡获取用户信息
public class MyRealm extends AuthorizingRealm {
@Override
//实现授权
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
return null;
}
@Override
//实现认证
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
String principal = (String) authenticationToken.getPrincipal();
//如果输入的是test,表示这个用户存在
if(principal.equals("test")){
//返回一个假数据,模拟从数据库取出:test|123
return new SimpleAuthenticationInfo("test","123",getName());
}
return null;
}
}
4、创建测试类,执行main方法,模拟用户登录
public class MyReamTest {
public static void main(String[] args) {
DefaultSecurityManager securityManager = new DefaultSecurityManager();
//设置realm为自定义的MyRealm
securityManager.setRealm(new MyRealm());
//给安全工具类,设置安全管理器
SecurityUtils.setSecurityManager(securityManager);
//从安全工具类中获取主体
Subject subject = SecurityUtils.getSubject();
//创建token
UsernamePasswordToken token = new UsernamePasswordToken("test","123");
try{
//登录
subject.login(token);
}catch (UnknownAccountException e){
System.out.println("登录账号不存在");
}
catch (IncorrectCredentialsException e){
System.out.println("登录密码不正确");
}
//判断登录成功
if(subject.isAuthenticated()){
System.out.println("登录成功");
}
}
}
?5、通过修改代码中用户名test,或者密码123,可以看到后台打印出对应账号或密码错误的日志
二、基本流程
1、首先,自定义的Realm,继承了AuthorizingRealm?
2、在调用subject.login(token)的时候,通过断点调试,会一步一步执行到如下图中的方法
3、当info为null,就会调用自定义realm中的doGetAuthenticationInfo方法。?
三、密码加盐
1、同样自定义一个realm,并继承AuthorizingRealm
?在认证的方法doGetAuthenticationInfo中,返回SimpleAuthenticationInfo对象时,需要提供盐值
public class MySaltRealm extends AuthorizingRealm {
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
String principal = (String) principalCollection.getPrimaryPrincipal();//主凭证,用来从数据库获取角色和权限等
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
info.addRoles(Arrays.asList("admin","user"));
info.addStringPermissions(Arrays.asList("user:create"));
return info;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
String principal = (String) authenticationToken.getPrincipal();
//test是模拟从数据库查出的账号,表示test账号存在数据库中
if("test".equals(principal)){
//894b3913a4a13b25dc6186d11835c209,是模拟从数据库查出的加密后的密码,该密码是经过MD5加密后的
//加密方式:Md5Hash str = new Md5Hash("123","abc",1024);
//参数:用户名、密码、盐值、realm名称
//加上盐值的参数,shiro在验证密码的时候,会自动加上盐值
return new SimpleAuthenticationInfo("test","894b3913a4a13b25dc6186d11835c209", ByteSource.Util.bytes("abc"),this.getName());
}
return null;
}
}
2、写个测试类,模拟登录
要给realm设置一个凭证匹配器,并指定加密算法、盐值和散列次数
public class MySaltRealmTest {
public static void main(String[] args) {
DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
AuthorizingRealm myRealm = new MySaltRealm();
//获取hash凭证匹配器
HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
//设置hash凭证匹配器使用的算法(MD5)
credentialsMatcher.setHashAlgorithmName("md5");
//如果使用散列(加密次数),则需要设置散列的次数:1024次
credentialsMatcher.setHashIterations(1024);
//给自定义的realm设置密码匹配器
myRealm.setCredentialsMatcher(credentialsMatcher);
//设置realm为自定义的realm
defaultSecurityManager.setRealm(myRealm);
SecurityUtils.setSecurityManager(defaultSecurityManager);
UsernamePasswordToken token = new UsernamePasswordToken("test","123");
Subject subject = SecurityUtils.getSubject();
try{
//认证
subject.login(token);
}catch (UnknownAccountException e){
e.printStackTrace();
System.out.println("账号出错");
}catch (IncorrectCredentialsException e){
e.printStackTrace();
System.out.println("密码出错");
}
if(subject.isAuthenticated()){
System.out.println("认证成功");
//判断权限
System.out.println("角色权限"+subject.hasRole("admin"));
System.out.println("资源权限"+subject.isPermitted("user:*"));
}
}
}
3、通过修改登录方法中的账号和密码,看控制台打印出对应的信息
|