概述
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环境准备三、 Shiro核心功能所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复