我是靠谱客的博主 霸气水蜜桃,最近开发中收集的这篇文章主要介绍Shiro初步学习(简介,环境,核心功能,核心组件)Shiro官网一、Shiro简介二、Shiro环境准备三、 Shiro核心功能,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

Shiro官网

尚硅谷教学视频

一、Shiro简介

  • Shiro是Apache提供的一个安全框架,Shiro提供了认证、授权、加密和会话管理等功能,对于任何一个应用程序,Shiro 都可以提供全面的安全管理服务。

有哪些功能?

  1. Authentication:身份认证/登录,验证用户是不是拥有相应的身份

  2. Authorization:授权,即权限验证,验证某个已认证的用户是否拥有某个权限;即判断用户是否能进行什么操作,如:验证某个用户是否拥有某个角色。或者细粒度的验证某个用户对某个资源是否具有某个权限

  3. Session Management:会话管理,即用户登录后就是一次会话,在没有退出之前,它的所有信息都在会话中;会话可以是普通JavaSE环境,也可以是Web 环境的

  4. Cryptography:加密,保护数据的安全性,如密码加密存储到数据库,而不是明文存储

  5. Web Support:Web 支持,可以非常容易的集成到Web 环境

  6. Caching:缓存,比如用户登录后,其用户信息、拥有的角色/权限不必每次去查,这样可以提高效率

  7. Concurrency:Shiro支持多线程应用的并发验证,即如在一个线程中开启另一个线程,能把权限自动传播过去

  8. Testing:提供测试支持

  9. “Run As”:允许一个用户假装为另一个用户(如果他们允许)的身份进行访问

  10. 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核心组件

  1. UsernamePasswordToken:Shiro 用来封装用户登录信息,使用用户的登录信息创建令牌 Token,登录的过程即 Shiro 验证令牌是否具有合法身份以及相关权限。

  2. SecurityManager:Shiro 的核心部分,负责安全认证与授权。

  3. Subject:Shiro 的一个抽象概念,包含了用户信息。

  4. Realm:开发者自定义的模块,根据项目的需求,验证和授权的逻辑在 Realm 中实现。

    • 一个Realm可以理解为能够访问特定于应用程序的安全数据(如用户,角色和权限)的组件。不管应用程序存在多少数据源以及任何类型的数据,Shiro都能通过Realm将其转换成易于理解的的程序化API格式。

    • Realm通常跟数据源(例如关系数据库,LDAP目录,文件系统或其他类似资源)具有1对1的关联关系。因此,Realm接口的实现使用特定于数据源的API来发现授权数据(角色,权限等),例如JDBC,文件IO,Hibernate,JPA,mybatis,ini文件或任何其他数据访问的API。

  5. AuthenticationInfo:用户的角色信息集合,认证时使用。

  6. AuthorizationInfo:角色的权限信息集合,授权时使用。

  7. DefaultWebSecurityManager:安全管理器,开发者自定义的 Realm 需要注入到 DefaultWebSecurityManager 进行管理才能生效。

  8. ShiroFilterFactoryBean:过滤器工厂,Shiro 的基本运行机制是开发者定制规则,Shiro 去执行,具体的执行操作就是由 ShiroFilterFactoryBean 创建一个个 Filter 对象来完成。

2.INI文件

  • shiro获取权限相关信息可以通过数据库获取,也可以通过ini配置文件获取

[users]
#k-v形式
zhangsan=z3
lisi=l4

3.登录认证

1.概述

  1. 身份验证:一般需要提供如身份ID等一些表示信息来表明登录者的身份,比如email,用户名/密码

  2. 在shiro中,用户需要提供 principals(身份)和 credentials(证明)给shiro,从而验证用户的身份

  3. principals:身份即主体标识属性,可以是任何属性,如用户名,邮箱,主体标识属性是唯一的,一个主体可以有多个principals,但只能有一个primary principal,一般是 用户名/密码 ,邮箱

  4. credentials:证明/凭证,即只有主体知道的安全值,如密码/数字证书

  5. 最常见的 principals 和 credentials 的组合就是用户名/密码

2.登录认证基本流程

  1. 收集用户身份/凭证,如:用户名/密码

  2. 调用 Subject.login 进行登录,如果失败将得到相应的 AuthenticationException异常,根据异常提示用户错误信息,否则登录成功

  3. 创建自定义的 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) 相关概念

  1. 授权:也叫控制访问,即在应用中控制谁访问哪些资源,

    授权中涉及到的几个关键对象:主体(subject),资源(resource),权限(permission),角色(role)

  2. 主体:即访问应用的用户,在shiro中用 Subject 代表用户

  3. 资源:在应用程序中可以访问的url,如jsp页面,用户只有被授权后才能访问

  4. 权限:应用中用户能否访问某个资源

  5. shiro支持粗粒度权限(如用户模块的所有权限),和细粒度权限(如实例级别的)

  6. 角色:权限的集合,一般情况下赋予用户的是角色而不是权限

(2) 授权方式

        1.编程式

        

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

 

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

(3) 角色授权流程

(4) 角色授权模拟

  1. 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) 判断权限信息

  1. 在 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核心功能所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(56)

评论列表共有 0 条评论

立即
投稿
返回
顶部