Apache Shiro 是一个功能强大且易于使用的 Java 安全(权限)框架。Shiro 可以完成:认证、授权、加密、会话管理、与 Web 集成、缓存 等。借助 Shiro 您可以快速轻松地保护任何应用程序——从最小的移动应用程序到最大的 Web 和企业应用程序。
官网:https://shiro.apache.org/
自 2003 年以来,框架格局发生了相当大的变化,因此今天仍然有很多系统在使用Shiro。这与 Shiro 的特性密不可分。
从外部来看 Shiro ,即从应用程序角度的来观察如何使用 Shiro 完成工作Shiro 架构
Shiro 架构
<dependencies>
<dependency>
<groupId>org.apache.shirogroupId>
<artifactId>shiro-coreartifactId>
<version>1.9.0version>
dependency>
<dependency>
<groupId>commons-logginggroupId>
<artifactId>commons-loggingartifactId>
<version>1.2version>
dependency>
dependencies>
Shiro 获取权限相关信息可以通过数据库获取,也可以通过 ini 配置文件获取
public class ShiroRun {
public static void main(String[] args) {
//1初始化获取SecurityManager
IniSecurityManagerFactory factory = new IniSecurityManagerFactory("classpath:shiro.ini");
SecurityManager securityManager = factory.getInstance();
SecurityUtils.setSecurityManager(securityManager);
//2获取Subject对象
Subject subject = SecurityUtils.getSubject();
//3创建token对象,web应用用户名密码从页面传递
AuthenticationToken token = new UsernamePasswordToken("zhangsan","123");
//4完成登录
try {
subject.login(token);
System.out.println("登录成功");
} catch (UnknownAccountException e){
e.printStackTrace();
System.out.println("用户不存在");
} catch (IncorrectCredentialsException e){
e.printStackTrace();
System.out.println("密码错误");
}catch (Exception e) {
e.printStackTrace();
}
}
}
if (subject.hasRole("admin")){
//有权限
} else {
//无权限
}
@RequiresRoles("admin")
public void test(){
//有权限
}
<shiro:hasRole name="admin">
shiro:hasRole>
//5.判断角色
boolean role1 = subject.hasRole("role1");
System.out.println("是否拥有此角色:"+role1);
//6.判断权限
boolean permitted = subject.isPermitted("user:insert111");
System.out.println("是否用有此权限:"+permitted);
//也可以用checkPermission方法,但没有返回值,没权限抛AuthenticationException
subject.checkPermission("user:select1111");
实际系统开发中,一些敏感信息需要进行加密,比如说用户的密码。Shiro 内嵌很多常用的加密算法,比如 MD5 加密。Shiro 可以很简单的使用信息加密。
使用Shiro进行密码加密.
public class ShiroMD5 {
public static void main(String[] args) {
String password = "123456";
//使用md5加密
// toHex():转换为它的HEX(十六进制)
Md5Hash md51 = new Md5Hash(password);
System.out.println("md5加密:"+md51.toHex());
//带盐的md5加密,盐就是在密码明文后拼接新字符串,然后再进行加密
Md5Hash md52 = new Md5Hash(password,"salt");
System.out.println("带盐的MD5加密:"+md52.toHex());
//为了保证安全,避免被破解还可以多次迭代加密,保证数据安全
Md5Hash md53 = new Md5Hash(password,"salt",3);
System.out.println("md5带盐的3次加密:"+md53.toHex());
//使用父类进行加密
SimpleHash simpleHash = new SimpleHash("MD5",password,"salt",3);
System.out.println("父类带盐的3次加密:"+simpleHash.toHex());
}
}
Shiro 默认的登录认证是不带加密的,如果想要实现加密认证需要自定义登录认证,自定义 Realm。
public class MyRealm extends AuthenticatingRealm {
//自定义登录认证方法,shiro的login方法底层会调用该类的认证方法进行认证
//需要配置自定义的realm生效,在ini文件中配置,在Springboot中配置
//该方法只是获取进行对比的信息,认证逻辑还是按照shiro底层认证逻辑完成
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//1.获取身份信息
String principal = authenticationToken.getPrincipal().toString();
//2.获取凭证信息
String password = new String((char[])authenticationToken.getCredentials());
System.out.println("认证用户信息:"+principal + "----"+password);
//3.获取数据库中存储的用户信息
if (principal.equals("zhangsan")){
//3.1数据库中存储的加盐3次迭代的密码
String pwdInfo = "d1b129656359e35e95ebd56a63d7b9e0";
//4创建封装校验逻辑对象,封装数据返回
AuthenticationInfo info = new SimpleAuthenticationInfo(
authenticationToken.getPrincipal(),
pwdInfo,
ByteSource.Util.bytes("salt"),
authenticationToken.getPrincipal().toString()
);
return info;
}
return null;
}
}
[main]
md5CredentialsMatcher=org.apache.shiro.authc.credential.Md5CredentialsMatcher
md5CredentialsMatcher.hashIterations=3
myrealm=com.shiro.MyRealm //自定义realm的路径
myrealm.credentialsMatcher=$md5CredentialsMatcher
securityManager.realms=$myrealm
[users]
zhangsan=d1b129656359e35e95ebd56a63d7b9e0,role1,role2
lisi=456
[roles]
role1:insert,user:select
结束!!!
个性像白纸,一经污染,便永不能再如以前的洁白。——黑格尔