zoukankan      html  css  js  c++  java
  • Shiro

    $Shiro

    Apache-shiro 是一种简便的java安全框架,对于身份认证,授权 。权限管理有着很简单的使用方法

    三个核心组件:Subject, SecurityManager 和 Realms.
     
     

    subject :访问当前系统的用户   主体可以是用户也可以是程序  。

    Shrio SecurityManager :安全管理器 ,shiro 的核心。类似于SpringMVC的前端控制器(DispatcherServlet),接收来自 “subject” 的委托,与认证器 ,授权器等进行交互

    Realm:相当于dataSource 安全的数据源   充当了shiro 与 数据源 的 “连接器” 当执行认证,授权时,shiro会从realm中比对信息是否合法合理。

    Shiro认证(使用ini方式进行测试)---> 所有项目均使用maven方式编写 

    shiro.ini(创建一个配置文件存放信息 。模拟从数据库中获取信息)

    [users]
    #账号=密码
    chen=123
    root=10001

    新建一个测试类

    加载配置文件 获取当前用户信息

    通过单独测试编写两个异常信息 ,反馈当用户名出错 或者密码出错的情况,

    package com.shiro.test;
    
    import org.apache.shiro.SecurityUtils;
    import org.apache.shiro.authc.IncorrectCredentialsException;
    import org.apache.shiro.authc.UnknownAccountException;
    import org.apache.shiro.authc.UsernamePasswordToken;
    import org.apache.shiro.config.IniSecurityManagerFactory;
    import org.apache.shiro.mgt.SecurityManager;
    import org.apache.shiro.subject.Subject;
    import org.apache.shiro.util.Factory;
    import org.junit.Test;
    
    /**
     * 测试shiro
     * 
     * @author 18609
     *
     */
    public class ShiroTest {
    
        
    
        @Test
        public void logintest() {
    
            // 创建工厂,加载资源 shiro工厂 调用Factory接口
            Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro-realm.ini");
            // 通过工厂对象创建SecurityManager对象
            SecurityManager manager = factory.getInstance();
            // 将SecurityManager绑定当前环境中。让系统随时访问SecurityManager对象
            SecurityUtils.setSecurityManager(manager);
            // 创建当前登陆主体 未认证
            Subject subject = SecurityUtils.getSubject();
            // 收集当前用户信息
            UsernamePasswordToken token = new UsernamePasswordToken("root", "10001");
            try {
                subject.login(token);
                System.out.println("登录成功");
            } catch (IncorrectCredentialsException e) { // 密码异常错误
                System.out.println("登陆失败,密码错误!");
            } catch (UnknownAccountException e) { // 账号异常错误
                System.out.println("登陆失败,账号不存在!");
            } finally {
                subject.logout();
                System.out.println("注销成功");
            }
        }
    }

    通过token 获取到username  并传给Realm验证 ,如果存在相同数据,封装成如下AuthenticationInfo对象进行返回  否则为null

    自定义一个Realm类 继承 AuthenticatingRealm 并复写其类的getName() 实现两个方法  进行认证操作

    package com.shiro.Realm;
    
    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.authz.AuthorizationInfo;
    import org.apache.shiro.realm.AuthenticatingRealm;
    import org.apache.shiro.subject.PrincipalCollection;
    
    public class MyRealm extends AuthenticatingRealm {
    
        // 重写 注意返回值
        public String getName() {
            return "MyRealm";
        }
    
        // 授权
            protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
                return null;
            }
            
        // 认证
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
    
            System.out.println(token);
            // 获取用户名
            String username = (String) token.getPrincipal();
            // 通过用户名查询 并返回
            if (!"root".equals(username)) {
                return null;
            }
            String password = "10001";
            // 对比当前信息
            SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username, password, getName());
            return info;
    
        }
    
    }

    shiro-realm.ini

    #自定义realm
    MyRealm=com.shiro.Realm.MyRealm
    #指定自定义realm的实现
    securityManager.realms=$MyRealm

     执行流程       

    认证成功

     Shiro加密认证(使用ini方式进行测试)---> 所有项目均使用maven方式编写 

    shiro 对md5加密有着较好的支持,这里不说明为什么要进行加密措施。

    测试几种加密方法  越往下 加密措施越好。越不易破解(以下加密方式全选用第三种  密码  + salt  + 散列次数

    package com.shiro.test;
    
    import org.apache.shiro.crypto.hash.Md5Hash;
    import org.junit.Test;
    
    public class Md5Test {
    
        @Test
        public void test() {
            String password = "10001";
            // 密码加密
            Md5Hash hash = new Md5Hash(password);
            System.out.println("password: " + hash);
            // 密码 + salt(用户名)
            Md5Hash hash1 = new Md5Hash(password, "root");
            System.out.println("passsword + salt :" + hash1);
            // 密码 + salt(用户名) + 散列次数   安全性能更好
            Md5Hash hash2 = new Md5Hash(password, "root", 3);
            System.out.println("passsword + salt + count :" + hash2);
        }
    
    }

    测试类

    package com.shiro.test;
    
    import org.apache.shiro.SecurityUtils;
    import org.apache.shiro.authc.IncorrectCredentialsException;
    import org.apache.shiro.authc.UnknownAccountException;
    import org.apache.shiro.authc.UsernamePasswordToken;
    import org.apache.shiro.config.IniSecurityManagerFactory;
    import org.apache.shiro.mgt.SecurityManager;
    import org.apache.shiro.subject.Subject;
    import org.apache.shiro.util.Factory;
    import org.junit.Test;
    
    /**
     * 测试shiro
     * 
     * @author 18609
     *
     */
    public class ShiroTest {
    
        @Test
        public void loginByPasswordtest() {
    
            // 创建工厂,加载资源 shiro工厂 调用Factory接口
            Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro-md5.ini");
            // 通过工厂对象创建SecurityManager对象
            SecurityManager manager = factory.getInstance();
            // 将SecurityManager绑定当前环境中。让系统随时访问SecurityManager对象
            SecurityUtils.setSecurityManager(manager);
            // 创建当前登陆主体 未认证
            Subject subject = SecurityUtils.getSubject();
            // 收集当前用户信息
            UsernamePasswordToken token = new UsernamePasswordToken("root", "10001");
            try {
                subject.login(token);
                System.out.println("登录成功");
            } catch (IncorrectCredentialsException e) { // 密码异常错误
                System.out.println("登陆失败,密码错误!");
            } catch (UnknownAccountException e) { // 账号异常错误
                System.out.println("登陆失败,账号不存在!");
            } finally {
                subject.logout();
                System.out.println("注销成功");
            }
        }
    }

    新建passwordRealm类 进行加密认证

    package com.shiro.Realm;
    
    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.authz.AuthorizationInfo;
    import org.apache.shiro.realm.AuthorizingRealm;
    import org.apache.shiro.subject.PrincipalCollection;
    import org.apache.shiro.util.ByteSource;
    
    public class PasswordRealm extends AuthorizingRealm {
    
        //注意返回值
    public String getName() { return "PasswordRealm"; } // 授权 protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { return null; } // 认证 protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { System.out.println(token); // 获取用户名 String username = (String) token.getPrincipal(); // 通过用户名查询 并返回 if (!"root".equals(username)) { return null; } // passsword + salt + count :2634402341f810a1007d7c4b4521aef5 String password = "2634402341f810a1007d7c4b4521aef5"; // 对比当前信息 1.用户名 2.密码 3.salt(加盐加密ByteSource.Util.bytes("root")) 4.重写当前的realm名字 SimpleAuthenticationInfo info = new SimpleAuthenticationInfo (username, password, ByteSource.Util.bytes("root"),getName()); return info; } }

     ByteSource.Util.bytes("root")  :进行盐(salt)加密认证   内填用户名

    不写此参数使用salt加密 会报错。报密码错误的问题 因为没有进行用户名认证。

    shiro-md5.ini

    填写与测试中相关的信息  红色标注不能更改必填项  蓝色标注更改项。

    #定义凭证匹配器
    credentialsMatcher=org.apache.shiro.authc.credential.HashedCredentialsMatcher
    #散列算法
    credentialsMatcher.hashAlgorithmName=md5
    #散列次数
    credentialsMatcher.hashIterations=3
    #指定passwordRealm的realm
    myRealm=com.shiro.Realm.PasswordRealm
    #引用凭证
    myRealm.credentialsMatcher=$credentialsMatcher
    #引用指定realm
    securityManager.realms=$myRealm

    通过设置加密的密码 存入数据库中 ,并进行加密认证 数据相同时,通过认证。登录成功。

  • 相关阅读:
    华为超大云数据中心落地贵州,这些硬核技术有利支撑“东数西算”
    在高并发环境下该如何构建应用级缓存
    使用 Python Poetry 进行依赖管理
    AI新手语音入门:认识词错率WER与字错率CER
    一文带你了解什么是GitOps
    需求蔓延,常见但不正常,教你如何破
    云图说|初识ModelArts开发者生态社区——AI Gallery
    XML学习笔记:关于字符编码的理解~
    Python中单引号、双引号和三双引号的区别:
    LBFGS算法的使用~
  • 原文地址:https://www.cnblogs.com/CllOVER/p/10386304.html
Copyright © 2011-2022 走看看