1. shiro基本使用
1.1 导入maven依赖
<dependencies>
<!--shiro核心包-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.13.0</version>
</dependency>
<!--需要的日志记录-->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
1.2 开始使用
准备 shiro.ini 文件用于测试,此为真正的用户名密码和权限信息
; [users]表示后面的配置项是用户
; 其中 root = 123456, admin,
; 表示用户名为root,密码为123456,角色为admin
[users]
root = 123456, admin
guest = abc123, guest, user:create
; [roles]表示后面的配置项是角色(角色是一组权限的集合,拥有了角色相当于拥有了该角色的所有权限)
; 其中 admin = *
; 表示角色admin,拥有所有权限
; 而 guest = user:insert
; 表示角色guest,拥有user:insert权限
[roles]
admin = *
guest = user:insert
书写ShiroRun测试类,模拟测试登录校验功能
// 指定的 shiro.ini 文件,获取相关安全配置信息
IniSecurityManagerFactory factory = new IniSecurityManagerFactory("classpath:shiro.ini");
// 通过指定的配置信息获取 SecurityManager实例
SecurityManager securityManager = factory.getInstance();
// 设置全局SecurityManager
SecurityUtils.setSecurityManager(securityManager);、
// 获取当前线程的Subject对象
Subject currentUser = SecurityUtils.getSubject();
// 创建token对象(用户提供的需要验证的信息,这里登录root账号)
UsernamePasswordToken token = new UsernamePasswordToken("root", "123456");
// 可选:记住此信息
token.setRememberMe(true);
// 登录
try {
//登录核心代码,如果用户名密码与提供的不符合会抛出异常,具体看后面的catch
currentUser.login(token);
System.out.println("登录成功");
} catch (UnknownAccountException uae) {
System.out.println("用户名不存在");
} catch (IncorrectCredentialsException ice) {
System.out.println("错误的验证信息");
} catch (LockedAccountException lae) {
System.out.println("账户锁定");
} catch (AuthenticationException ae) {
System.out.println("其他错误");
}
// 登出
currentUser.logout();
执行结果
1.3 自定义realm规则
一般我们都不会从ini文件中获取认证信息,而是通过从数据库中获取的方式拿出,下面模拟了从数据库中取出数据的时候shiro书写的方式。
书写MyRealm类,继承AuthenticatingRealm实现doGetAuthenticationInfo方法。
此方法的参数为 AuthenticationToken,可以认为其传入参数为之前的 login(token) 方法所传入的。
在 doGetAuthenticationInfo 中我们主要的是提供(返回)一个正确的密码,然后交给 shiro 进行密码验证。
public class MyRealm extends AuthenticatingRealm {
// shiro的login方法会调用此类的认证方法进行认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
String username = (String) token.getPrincipal(); // 获取要登录的用户名
//查找用户名是否存在
// 注:由于没有连接数据库,这里的逻辑是验证 用户名root密码123456的用户 。
if ("root".equals(username)) {
// 获取用户真实的密码,这里用123456直接赋值代替
String truePassword = "123456";
// 返回要比较的信息以及其他参数(重点是密码),交付给shiro 进行密码验证。
return new SimpleAuthenticationInfo(
username, //用户的信息
truePassword, //密码
this.getName() //realm name , 用于区分不同realm
);
}
return null; // 返回null,表示用户不存在
}
}
使用自己实现的MyRealm,需要在原来的基础上做些改变,我们不从ini文件中直接获取验证信息,而是从MyRealm获取信息检测。前面需要更改的代码:
// 获取默认的安全管理
DefaultSecurityManager securityManager = new DefaultSecurityManager();
// 设置自己的MyReal
securityManager.setRealm(new MyRealm());
// 设置为全局SecurityManager
SecurityUtils.setSecurityManager(securityManager);
// 获取当前线程的Subject对象
Subject currentUser = SecurityUtils.getSubject();
// 具体权限操作...
2. shiro的md5加密
关于md5加密
md5加密可以用于对信息进行加密处理,一般是密码等隐私信息。它是一种不可逆的加密,无法进行解密操作(1996年后该算法被证实存在弱点,可以被加以破解,对于需要高度安全性的数据,一般建议改用其他算法)。
通常用来将用户的真实密码经过md5加密处理后存储起来。然后在需要验证密码的时候,将用户输入的密码进行同样的md5加密操作,和存储的密码对比查看是否正确。
shiro的md5加密只需要使用类Md5Hash
即可
使用的类:
import org.apache.shiro.crypto.hash.Md5Hash;
2.1 基本md5加密
Md5Hash md5Hash = new Md5Hash("123456"); //获取字符串的md5加密值
String md5 = md5Hash.toHex(); //获取md5的字符串,使用toHex()方法,当然toString()也可以
System.out.println("md5 = " + md5);
//md5 = e10adc3949ba59abbe56e057f20f883e
2.2 带盐的md5加密
带盐就是添加一个前缀然后在进行加密(防止md5加密被破解)
Md5Hash md5HashWithSalt = new Md5Hash("123456", "yan"); //带盐MD5加密
String md5WithSalt = md5HashWithSalt.toHex();
System.out.println("md5WithSalt = " + md5WithSalt);
//md5WithSalt = c629497ab255cb1a56e9df3f78418944
上方的带盐的md5加密与下面的操作等同
Md5Hash md5HashWithSalt = new Md5Hash("yan" + "123456"); //手动拼接字符串的带盐MD5加密 String md5WithSalt = md5HashWithSalt.toHex(); System.out.println("md5WithSalt = " + md5WithSalt); //md5WithSalt = c629497ab255cb1a56e9df3f78418944
2.3 迭代带盐的md5加密
迭代就是多使用几次md5加密功能(也是防止md5加密被破解)
Md5Hash md5Repeat3 = new Md5Hash("123456", "yan", 3); //迭代带盐的md5加密
System.out.println("md5Repeat3 = " + md5Repeat3.toHex());
//md5Repeat = 852b483eac9b40d05cad3a4db34c14e6
上方的迭代带盐的md5加密与下面的操作等同
Md5Hash md5Repeat1 = new Md5Hash("123456", "yan"); //带盐MD5加密1 Md5Hash md5Repeat2 = new Md5Hash(md5Repeat1); //MD5加密2 Md5Hash md5Repeat3 = new Md5Hash(md5Repeat2); //MD5加密3 System.out.println("md5Repeat3 = " + md5Repeat3.toHex()); //md5Repeat = 852b483eac9b40d05cad3a4db34c14e6 ```![![image-20240502143058151.png](https://upload-images.jianshu.io/upload_images/29350904-a8bbbdace1d1f10b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)