首页 > 其他分享 >springboot整合shiro

springboot整合shiro

时间:2023-02-28 13:26:19浏览次数:39  
标签:加密 springboot System token 整合 println subject shiro out

1. 什么是Shiro

Shiro是一个基于Java的安全框架,它提供了身份验证授权加密和会话管理等安全功能,可以帮助Java应用程序实现安全性。



2. 根据Shiro的基本使用了解其基本原理

1. 添加依赖

    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-core</artifactId>
        <version>1.9.0</version>
    </dependency>

2. 创建ini文件,实现登录功能

    在resources文件目录下创建 后缀为 .ini 的文件。内容如下:
      [users]
      zhangsan=123
      lisi=123
    解释:表示创建了一个2个用户  分别是shangsan,lisi。他们的密码都是123。

    //////////////////////////

    subject.login 认证的原理如下:
      1. 首先调用 Subject.login(token) 进行登录,其会自动委托给 SecurityManager
      2. SecurityManager 负责真正的身份验证逻辑;它会委托给 Authenticator 进行身份验证
      3. Authenticator 才是真正的身份验证者,Shiro API 中核心的身份 认证入口点,此处可以自定义插入自己的实现
      4. Authenticator 可能会委托给相应的 AuthenticationStrategy 进 行多 Realm 身份验证,默认 ModularRealmAuthenticator 会调用 AuthenticationStrategy 进行多 Realm身份验证
      5. Authenticator 会把相应的 token 传入 Realm,从 Realm 获取 身份验证信息,如果没有返回/抛出异常表示身份验证失败了。此处 可以配置多个Realm,将按照相应的顺序及策略进行访问

      自己总结:就是说 subject.login 最后其实调用的是 AuthenticatingRealm 类下的 doGetAuthenticationInfo(token) 方法

    //////////////////////////
    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","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 ae) {
                //unexpected condition? error?
            }
        }
    }

3. 利用shiro提供加密

    Shiro 内嵌了很多常用的加密算法,比如MD5加密。
    常见的加密算法:
        对称加密:加密,解密使用同一个秘钥进行,常见的有 DES、3DES、AES 等。
        非对称加密:使用一对密钥(公钥和私钥是一对)进行加密和解密,常见的有 RSA、DSA、ECC 等。
        消息摘要算法:把任意长度的输入揉和而产生长度固定的伪随机结果的算法。常见的有 MD5、SHA-1、SHA-256、SHA-512 等。
        数字签名算法:数字签名算法主要是为了解决消息的真实性和完整性问题,常见的有 RSA 签名、DSA 签名、ECDSA 签名等。

    MD5:
        被称为信息摘要算法,所谓的信息摘要就是把明文内容按一定规则生成一段哈希(hash)值,即得到这段明文内容的信息摘要。
        md5是不可逆的,也就是没有对应的算法,从生产的md5值逆向得到原始数据。但是可以通过暴力解析得到原始数据。一般不会直接使用,都会对密码进行加盐处理。

    SHA-256:
        也被称为信息摘要算法,对于任意长度的消息,SHA256都会产生一个256位的哈希值。[总之,是目前很安全的加密算法,推荐]

    // 使用Shiro提供的MD5进行加密:
    public class ShiroMD5 {
        public static void main(String[] args) {
            // 密码明文
            String password = "z3";

            // 使用 md5 加密
            Md5Hash md5Hash = new Md5Hash(password);
            System.out.println("md5 加密:"+md5Hash.toHex());

            // 带盐的 md5 加密,盐就是在密码明文后拼接新字符串,然后再进行加密
            Md5Hash md5Hash2 = new Md5Hash(password,"salt");
            System.out.println("md5 带盐加密:"+md5Hash2.toHex());

            // 为了保证安全,避免被破解还可以多次迭代加密,保证数据安全
            Md5Hash md5Hash3 = new Md5Hash(password,"salt",3);
            System.out.println("md5 带盐三次加密:"+md5Hash3.toHex());
        }
    }
            

4. 授权(授予角色,授予权限)

    授权方式可以分为:
        编程式:
            if(subject.hasRole("root")){ 
              // 有权限
            } else{
              // 没权限
            }
  
        注解式:
            @RequiresRoles("admin")
            public MsgResult listUser(){
              
            }

    /////////////////////////

    更改.ini文件:
        [users]
        zhangsan=shangsan,role1,role2
        lisi=lisi

        [roles]
        role1=user:list,user:insert
      解释:
        表示zhangsan用户拥有role1与role2角色
        role1角色拥有 user:list 的权限,  role2角色拥有 user:insert 权限
        【这里的 user:list 只是一种标识,可以任意定义,表示role1具有某种权限字符串,拥有该权限字符串,就能让它有什么权限】
  
    /////////////////////////
    
    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","z3");
            //4 完成登录
            try {
                subject.login(token);
                System.out.println("登录成功");
                // 判断角色
                if(subject.hasRole("role1")){
                    System.out.println("该用户拥有角色:role1")
                }
                // 判断权限
                if(subject.isPermitted("user:insert")){
                    System.out.println("该用户拥有权限:user:insert")
                }
            } catch (UnknownAccountException e) {
                e.printStackTrace();
                System.out.println("用户不存在");
            } catch (IncorrectCredentialsException e) {
                e.printStackTrace();
                System.out.println("密码错误");
            } catch (AuthenticationException ae) {
                //unexpected condition? error?
            }
        }
    }

3. 使用自定义Realm更改shiro的默认登录操作

    更改.ini文件:
        [main]
        md5CredentialsMatcher=org.apache.shiro.authc.credential.Md5CredentialsMatcher
        md5CredentialsMatcher.hashIterations=3
        myrealm=com.lihao.config.realm.MyRealm
        myrealm.credentialsMatcher=$md5CredentialsMatcher
        securityManager.realms=$myrealm

        [users]
        zhangsan=7174f64b13022acd3c56e2781e098a5f,role1,role2
        lisi=root

        [roles]
        role1=user:insert,user:select

    /////////////////////////////

    // subject.login(token) 实现登录,它的本质调用的是 AuthenticatingRealm 类下的 doGetAuthenticationInfo(token) 方法。

    我们想改造shiro的登录,就可以继承AuthenticatingRealm类,重写doGetAuthenticationInfo(token) 方法以达到我们想在登录功能里面进行的额外操作。

    public class MyRealm extends AuthenticatingRealm {
        // 这个类是我们自己写的,需要配置自定义的 realm 生效,在 ini 文件中配置,或 Springboot 中配置
        // 该方法终究能操作的只是部分登录认证(对比密码),真正认证逻辑还是按照 Shiro 的底层认证逻辑完成认证。
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
            // 方法参数:AuthenticationToken 是个接口。  
                  有2个属性:principal(username),credentials(password)    
                  有2个子接口:RememberMeAuthenticationToken(有1个属性:isRememberMe),HostAuthenticationToken(有1个属性:getHost)
                      这2个子接口,都有一个共同的实现类:public class UsernamePasswordToken implements HostAuthenticationToken, RememberMeAuthenticationToken

            //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 = "7174f64b13022acd3c56e2781e098a5f";
                //3.2 创建封装了校验逻辑的对象,将要比较的数据给该对象
                AuthenticationInfo info = new SimpleAuthenticationInfo(authenticationToken.getPrincipal(),
                pwdInfo,ByteSource.Util.bytes("salt"), this.getName());
                return info;
            }
            return null;
        }
    }

4. SpringBoot整合Shiro

标签:加密,springboot,System,token,整合,println,subject,shiro,out
From: https://www.cnblogs.com/itlihao/p/17162334.html

相关文章

  • Shiro架构
    作用shiro是认证、授权管理的框架。 核心组件   subject:用户,但不一定指的是人authenticator:认证器authorizer:授权器realm:用户的权限获取,一般通过与D......
  • SSM整合
    1、基本的项目环境搭建1.1、准备数据库首先建立表和数据(这里要注意就是mysql版本不一样,语句也是有变化的)DROPTABLEIFEXISTS`books`;CREATETABLE`books`(`bo......
  • SpringBoot全局异常封装:AOP增强
    api请求错误返回json,页面请求错误跳转报错页面:自动装配、异常通知两个方法Java异常类错误无法避免,通常由于系统原因造成。如IOError,注意不是IOException,原因可能是......
  • 【spring笔记】Spring整合Mybaties
    官方文档:http://mybatis.org/spring/zh/sqlsession.html1、实现方式1核心思想:利用Spring配置依赖注入创建sqlSessionFactory和sqlSession实例需要的包如下:1.1、编......
  • springboot处理乱码问题原理
    我们在用spring-springmvc时,需要配置一个过滤器 CharacterEncodingFilterCharacterEncodingFilterfilter=newOrderedCharacterEncodingFilter();filter.setEncodin......
  • springboot集成easyexcel(阿里)
    poi比较占用内存。easyexcel性能优化不少,值得一看。pom.xml中添加:<dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>2.1.6</......
  • springboot中json参数映射
    文章目录​​json映射不到实体上​​​​问题分析​​​​解决方案​​​​json映射到String查不到数据​​​​问题分析​​​​解决方案​​​​自动映射入参可以多吗,可以......
  • 转载:pageOffice插件 springboot实现服务器上Word文档在线打开编辑保存
    pageOffice插件springboot实现服务器上Word文档在线打开编辑保存需求:在oa系统上,想实现在线,服务器上doc,docx文档,在web打开,编辑。编辑后,可以再同步保存到服务器端。......
  • SpringBoot项目结构
    一.总体概述SpringBoot框架简单来说就是一个Web框架,其目的在于快速开发一个Web应用的后端实现主要包括三部分:java文件夹,Resource文件夹,pom.xml二.Java文件夹Co......
  • springboot+mybatis-plus数据库mysql+sybase遇到的一些问题
    我们服务启动时,sybase数据库连接直接创建10个连接。(为什么启动时会创建这么多连接?)有时候可以写入sybase库,大部分写入失败查询sybase库数据可以查出来,没问题尝试的方......