Shiro官网
尚硅谷教学视频
一、Shiro简介
-
Shiro是Apache提供的一个安全框架,Shiro提供了认证、授权、加密和会话管理等功能,对于任何一个应用程序,Shiro 都可以提供全面的安全管理服务。
有哪些功能?

-
Authentication:身份认证/登录,验证用户是不是拥有相应的身份
-
Authorization:授权,即权限验证,验证某个已认证的用户是否拥有某个权限;即判断用户是否能进行什么操作,如:验证某个用户是否拥有某个角色。或者细粒度的验证某个用户对某个资源是否具有某个权限
-
Session Management:会话管理,即用户登录后就是一次会话,在没有退出之前,它的所有信息都在会话中;会话可以是普通JavaSE环境,也可以是Web 环境的
-
Cryptography:加密,保护数据的安全性,如密码加密存储到数据库,而不是明文存储
-
Web Support:Web 支持,可以非常容易的集成到Web 环境
-
Caching:缓存,比如用户登录后,其用户信息、拥有的角色/权限不必每次去查,这样可以提高效率
-
Concurrency:Shiro支持多线程应用的并发验证,即如在一个线程中开启另一个线程,能把权限自动传播过去
-
Testing:提供测试支持
-
“Run As”:允许一个用户假装为另一个用户(如果他们允许)的身份进行访问
-
Remember Me:记住我,这个是非常常见的功能,即一次登录后,下次再来的话不用登录了
二、Shiro环境准备
maven引入shiro(官方)
<dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>1.11.0</version> </dependency> <!-- Shiro uses SLF4J for logging. We'll use the 'simple' binding in this example app. See https://www.slf4j.org for more info. --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> <version>1.7.21</version> <scope>test</scope> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>jcl-over-slf4j</artifactId> <version>1.7.21</version> <scope>test</scope> </dependency>
三、 Shiro核心功能
1.Shiro核心组件
-
UsernamePasswordToken:Shiro 用来封装用户登录信息,使用用户的登录信息创建令牌 Token,登录的过程即 Shiro 验证令牌是否具有合法身份以及相关权限。
-
SecurityManager:Shiro 的核心部分,负责安全认证与授权。
-
Subject:Shiro 的一个抽象概念,包含了用户信息。
-
Realm:开发者自定义的模块,根据项目的需求,验证和授权的逻辑在 Realm 中实现。
-
一个Realm可以理解为能够访问特定于应用程序的安全数据(如用户,角色和权限)的组件。不管应用程序存在多少数据源以及任何类型的数据,Shiro都能通过Realm将其转换成易于理解的的程序化API格式。
-
Realm通常跟数据源(例如关系数据库,LDAP目录,文件系统或其他类似资源)具有1对1的关联关系。因此,Realm接口的实现使用特定于数据源的API来发现授权数据(角色,权限等),例如JDBC,文件IO,Hibernate,JPA,mybatis,ini文件或任何其他数据访问的API。
-
-
AuthenticationInfo:用户的角色信息集合,认证时使用。
-
AuthorizationInfo:角色的权限信息集合,授权时使用。
-
DefaultWebSecurityManager:安全管理器,开发者自定义的 Realm 需要注入到 DefaultWebSecurityManager 进行管理才能生效。
-
ShiroFilterFactoryBean:过滤器工厂,Shiro 的基本运行机制是开发者定制规则,Shiro 去执行,具体的执行操作就是由 ShiroFilterFactoryBean 创建一个个 Filter 对象来完成。
2.INI文件
-
shiro获取权限相关信息可以通过数据库获取,也可以通过ini配置文件获取
[users] #k-v形式 zhangsan=z3 lisi=l4
3.登录认证
1.概述
-
身份验证:一般需要提供如身份ID等一些表示信息来表明登录者的身份,比如email,用户名/密码
-
在shiro中,用户需要提供 principals(身份)和 credentials(证明)给shiro,从而验证用户的身份
-
principals:身份即主体标识属性,可以是任何属性,如用户名,邮箱,主体标识属性是唯一的,一个主体可以有多个principals,但只能有一个primary principal,一般是 用户名/密码 ,邮箱
-
credentials:证明/凭证,即只有主体知道的安全值,如密码/数字证书
-
最常见的 principals 和 credentials 的组合就是用户名/密码
2.登录认证基本流程
-
收集用户身份/凭证,如:用户名/密码
-
调用 Subject.login 进行登录,如果失败将得到相应的 AuthenticationException异常,根据异常提示用户错误信息,否则登录成功
-
创建自定义的 Realm类,继承 org.apache.shiro.realm.AuthorizingRealm类,实现doGetAuthenticationInfo() 方法
3.模拟登录认证
package com.rossland.springbootshiro;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
/**
* @author RossLand
* 2023.2.15
*/
public class ShiroTest {
public static void main(String[] args) {
//1.初始化 SecurityManager对象 并 读取shiro配置文件
IniSecurityManagerFactory factory = new IniSecurityManagerFactory("classpath:shiro.ini");
SecurityManager securityManager = factory.getInstance();
SecurityUtils.setSecurityManager(securityManager);
//2.获取 Subject 对象
Subject subject = SecurityUtils.getSubject();
//3.创建token对象,web应用用户名密码从前端传递(这里用ini文件模拟)
AuthenticationToken token = new UsernamePasswordToken("张三","z3");
//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 (AuthenticationException e) {
e.printStackTrace();
System.out.println("未知错误");
}
}
}
4.角色授权
(1) 相关概念
-
授权:也叫控制访问,即在应用中控制谁访问哪些资源,
授权中涉及到的几个关键对象:主体(subject),资源(resource),权限(permission),角色(role)
-
主体:即访问应用的用户,在shiro中用 Subject 代表用户
-
资源:在应用程序中可以访问的url,如jsp页面,用户只有被授权后才能访问
-
权限:应用中用户能否访问某个资源
-
shiro支持粗粒度权限(如用户模块的所有权限),和细粒度权限(如实例级别的)
-
角色:权限的集合,一般情况下赋予用户的是角色而不是权限
(2) 授权方式
1.编程式

2.注解式:在方法上添加对应的注解

3.在 JSP/GSP 中使用相应标签

(3) 角色授权流程

(4) 角色授权模拟
-
在 shiro.ini文件中添加角色配置
[users] #k-v 张三=z3,roleA 李四=l4
2.代码如下
package com.rossland.springbootshiro;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
/**
* @author RossLand
* 2023.2.15
*/
public class ShiroTest {
public static void main(String[] args) {
//1.初始化 SecurityManager对象 并 读取shiro配置文件
IniSecurityManagerFactory factory = new IniSecurityManagerFactory("classpath:shiro.ini");
SecurityManager securityManager = factory.getInstance();
SecurityUtils.setSecurityManager(securityManager);
//2.获取 Subject 对象
Subject subject = SecurityUtils.getSubject();
//3.创建token对象,web应用用户名密码从前端传递(这里用ini文件模拟)
AuthenticationToken token = new UsernamePasswordToken("张三","z3");
//4.进行登录操作
try {
//登录
subject.login(token);
System.out.println("登录成功");
//5.判断角色
boolean hasRole = subject.hasRole("roleA");//true
System.out.println("该用户是否拥有此角色:"+hasRole);
} catch (UnknownAccountException e){
e.printStackTrace();
System.out.println("无此用户");
} catch (IncorrectCredentialsException e){
e.printStackTrace();
System.out.println("密码错误");
}
catch (AuthenticationException e) {
e.printStackTrace();
System.out.println("未知错误");
}
}
}
(5) 判断权限信息
-
在 shiro.ini 文件中添加角色权限配置
[users] #k-v 张三=z3,roleA 李四=l4 [roles] roleA=查询
2.代码如下
package com.rossland.springbootshiro;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
/**
* @author RossLand
* 2023.2.15
*/
public class ShiroTest {
public static void main(String[] args) {
//1.初始化 SecurityManager对象 并 读取shiro配置文件
IniSecurityManagerFactory factory = new IniSecurityManagerFactory("classpath:shiro.ini");
SecurityManager securityManager = factory.getInstance();
SecurityUtils.setSecurityManager(securityManager);
//2.获取 Subject 对象
Subject subject = SecurityUtils.getSubject();
//3.创建token对象,web应用用户名密码从前端传递(这里用ini文件模拟)
AuthenticationToken token = new UsernamePasswordToken("张三","z3");
//4.进行登录操作
try {
//登录
subject.login(token);
System.out.println("登录成功");
//5.判断角色
boolean hasRole = subject.hasRole("roleA");
System.out.println("该用户是否拥有此角色:"+hasRole);
/*
6.判断权限
可以用 isPermitted()方法 -> boolean类型,不会跑异常
或
checkPermission()方法 -> 无返回类型,若无权限会抛出 UnauthorizedException 异常
*/
boolean isPermitted = subject.isPermitted("查询");
System.out.println("该用户是否有该权限"+isPermitted);
subject.checkPermission("查询");
} catch (UnknownAccountException e){
e.printStackTrace();
System.out.println("无此用户");
} catch (IncorrectCredentialsException e){
e.printStackTrace();
System.out.println("密码错误");
}
catch (AuthenticationException e) {
e.printStackTrace();
System.out.println("未知错误");
}
}
}
5.shiro加密
package com.rossland.springbootshiro;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.crypto.hash.SimpleHash;
import sun.security.provider.MD5;
/**
* @author RossLand
* 2023.2.15
*/
public class Encryption {
public static void main(String[] args) {
//模拟密码
String password = "z3";
//使用MD5加密
Md5Hash md5Hash = new Md5Hash(password);
System.out.println("MD5加密后:"+md5Hash.toHex());
//toHex()是加密后的密文为16进制
//MD5带盐加密
Md5Hash md5Hash1 = new Md5Hash(password,"salt");
System.out.println("MD5带盐一次加密:"+md5Hash1);
Md5Hash md5Hash2 = new Md5Hash(password,"salt",2);
System.out.println("Md5带盐二次加密:"+md5Hash2);
//使用父类进行加密
SimpleHash simpleHash = new SimpleHash("MD5",password,"salt",2);
System.out.println("父类带盐二次加密:"+simpleHash);
}
}
运行结果如下
6.shiro自定义登录认证
-
Shiro默认的登录认证是不带加密的,如果想要实现加密认证需要自定义登录认证,自定义Realm
package com.rossland.springbootshiro;
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.realm.AuthenticatingRealm;
import org.apache.shiro.util.ByteSource;
/**
* @author RossLand
* 2023.2.15
*/
public class MyRealm extends AuthenticatingRealm {
//customized realm
//1.自定义Realm继承 AuthenticatingRealm 类
/**
2.shiro的 login方法底层会调用该类的认证方法
需要进行配置让自定义 realm 生效(ini文件,yml文件)
该方法只是获取进行对比的信息,认证逻辑由shiro底层完成
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//1.获取从前端传来的身份信息
String principal = authenticationToken.getPrincipal().toString();
//2.获取从前端传来的凭证信息
String credential = new String((char[]) authenticationToken.getCredentials());
System.out.println(principal + credential);
//3.获取数据库中存储的用户凭证信息(这里用ini文件中的信息模拟)
if (principal.equals("张三")){
//模拟从数据库中获取的二次加盐加密后的密文
String pwd = "a41d90f0ce66e09b276704c5a209a1ab";
//4.创建封装校验逻辑对象,封装数据返回
AuthenticationInfo info = new SimpleAuthenticationInfo(
authenticationToken.getPrincipal(),
pwd,
ByteSource.Util.bytes("salt"),
authenticationToken.getPrincipal().toString()
);
/* 第一个参数:传入的都是com.java.entity包下的User类的user对象。
注意:此参数可以通过subject.getPrincipal()方法获取—获取当前记录的用户,从这个用户对象进而再获取一系列的所需要的属性。
第二个参数: 传入的是从数据库中获取到的password,然后再与token中的password进行对比,匹配上了就通过,匹配不上就报异常。
第三个参数,盐–用于加密密码对比。 若不需要,则可以设置为空 “ ”
第四个参数:当前realm的名字,当前realm是ini文件中的"张三" */
return info;
}
return null;
}
}
-
模拟自定义realm类,下面是使用ini文件作为数据源
[main]
md5CredentialsMatcher=org.apache.shiro.authc.credential.Md5CredentialsMatcher
md5CredentialsMatcher.hashIterations=2
myrealm= com.rossland.springbootshiro.MyRealm
myrealm.credentialsMatcher=$md5CredentialsMatcher
securityManager.realms=$myrealm
最后
以上就是霸气水蜜桃最近收集整理的关于Shiro初步学习(简介,环境,核心功能,核心组件)Shiro官网一、Shiro简介二、Shiro环境准备三、 Shiro核心功能的全部内容,更多相关Shiro初步学习(简介,环境,核心功能,核心组件)Shiro官网一、Shiro简介二、Shiro环境准备三、内容请搜索靠谱客的其他文章。
发表评论 取消回复