Shiro基础

shiro

为什么要⽤shiro:
1.项⽬中的密码是否可以明⽂存储?
2.是否任意访客,⽆论是否登录都可以访问任何功能?
3.项⽬中的各种功能操作,是否是所有⽤户都可以随意使⽤?
综上,当项⽬中的某些功能被使⽤时,需要进⾏安全校验,进⽽保证整个系统的运⾏秩序。

shiro是什么

  • Apache Shiro 是 Java 的⼀个安全(权限)框架。
    Shiro 可以轻松的完成:身份认证、授权、加密、会话管理等功能
  • Shiro 可以⾮常容易的开发出⾜够好的应⽤,其不仅可以⽤在JavaSE 环境,也可以⽤在 JavaEE 环境。
    功能强⼤且易⽤,可以快速轻松地保护任何应⽤程序 ( 从最⼩的移动应⽤程序到最⼤的Web和企业应⽤程序。)
  • ⽅便的与Web 集成和搭建缓存。

功能介绍

在这里插入图片描述

  • Authentication:身份认证/登录,验证⽤户是不是拥有相应的身份;
  • Authorization:授权,即权限验证,验证某个已认证的⽤户是否拥有某个权限;即判断⽤户是否能进⾏什么操作。如:验证某个⽤户是否拥有某个⻆⾊。或者细粒度的验证某个⽤户对某个资源是否具有某个权限;
  • Session Manager:会话管理,即⽤户登录后就是⼀次会话,在没有退出之前,它的所有信息都在会话中;会话可以是普通 JavaSE 环境,也可以是 Web 环境的;
  • Cryptography:加密,保护数据的安全性,如密码加密存储到数据库,⽽不是明⽂存储;
  • Web Support:Web ⽀持,可以⾮常容易的集成到Web 环境;
  • Caching:缓存,⽐如⽤户登录后,其⽤户信息、拥有的⻆⾊/权限不必每次去查,这样可以提⾼效率;
  • Remember Me:记住我,这个是⾮常常⻅的功能,即⼀次登录后,下次再来的话可以⽴即知道你是哪个⽤户

工作流程

在这里插入图片描述

  • • Subject
    安全校验中,最常⻅的问题是"当前⽤户是谁?" “当前⽤户是否有权做x事?”,所以考虑安全校验过程最⾃
    然的⽅式就是基于当前⽤户。Subject 代表了当前“⽤户”,
    应⽤代码直接交互的对象是 Subject,只要得到Subject对象⻢上可以做绝⼤多数的shiro操作。
    也就是说 Shiro 的对外API 核⼼就是 Subject。
    Subject 会将所有交互都会委托给 SecurityManager。
    Subject是安全管理中直接操作的对象
  • SecurityManager
    安全管理器;即所有与安全有关的操作都会与SecurityManager 交互;
    且其管理着所有 Subject;它是 Shiro的核⼼,
    它负责与 Shiro 的其他组件进⾏交互,它相当于 SpringMVC 中DispatcherServlet 的⻆⾊
  • Realm
    Shiro 从 Realm 获取安全数据(如⽤户、⻆⾊、权限),就是说SecurityManager 要验证⽤户身份,那么
    它需要从 Realm 获取相应的⽤户进⾏⽐较以确定⽤户身份是否合法;
    也需要从 Realm 得到⽤户相应的⻆⾊/权限进⾏验证⽤户是否能进⾏操作;
    可以把 Realm 看成 DAO,( 数据访问⼊⼝ )

框架了解

  • Subject:任何可以与应⽤交互的“⽤户”;
  • SecurityManager:相当于SpringMVC 中的 DispatcherServlet;是 Shiro 的⼼脏;
    所有具体的交互都通过 SecurityManager 进⾏控制;它管理着所有 Subject、且负责进⾏认证、授权、会话及
    缓存的管理。
  • Authenticator:负责 Subject 身份认证,是⼀个扩展点,可以⾃定义实现;可以使⽤认证
    策略(Authentication Strategy),即什么情况下算⽤户认证通过了;
  • Authorizer:授权器、即访问控制器,⽤来决定主体是否有权限进⾏相应的操作;即控制着⽤户能访问应⽤中的哪些功能;
  • Realm:可以有 1 个或多个 Realm,可以认为是安全实体数据源,即⽤于获取安全实体
    的;可以是JDBC 实现,也可以是内存实现等等;由⽤户提供;所以⼀般在应⽤中都需要实现⾃⼰的 Realm;
  • SessionManager:管理 Session ⽣命周期的组件;⽽ Shiro 并不仅仅可以⽤在 Web环境,也可以⽤在如普通的 JavaSE 环境
  • CacheManager:缓存控制器,来管理如⽤户、⻆⾊、权限等的缓存的;因为这些数据基本上很少改变,
    放到缓存中后可以提⾼访问的性能
  • Cryptography:密码模块,Shiro 提供了⼀些常⻅的加密组件⽤于如密码加密/解密。

1,shiro认证

  • shiro基础一:

  • 引入maven
    <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <version>1.5.3</version>
        </dependency>
  • 在resources创建shiro.ini文件在这里插入图片描述
[users]
xiaochen=123
zhangsan=123456
lisi=789
  • 建立TestAuthenticator累
public static void main(String[] args) {
        //创建安全管理器
        DefaultSecurityManager securityManager = new DefaultSecurityManager();

        //给安全管理器设置realm
        securityManager.setRealm(new IniRealm("classpath:shiro.ini"));

        //SecurityUtils全局安全工具类,有认证和退出的相关方法
        SecurityUtils.setSecurityManager(securityManager);

        //创建关键对象
        Subject subject = SecurityUtils.getSubject();

        //创建令牌
        UsernamePasswordToken token = new UsernamePasswordToken("zhangsan","123456");

        try{
            System.out.println("认证状态:上"+subject.isAuthenticated());
            subject.login(token); //用户认证
            System.out.println("认证状态:下"+subject.isAuthenticated());
        }catch (UnknownAccountException e){
            e.printStackTrace();
            System.out.println("认证失败,用户名不存在");
        }catch (IncorrectCredentialsException e){
            e.printStackTrace();
            System.out.println("认证失败,密码不正确");
        }
    }
  • 测试

在这里插入图片描述

shiro基础二:自定义realm

  • 创建CustomerRealm累继承AuthorizingRealm
/**
 * 自定义realm实现 将认证、授权的数据来源转为数据库的实现
 */
public class CustomerRealm extends AuthorizingRealm {

    //授权
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        return null;
    }

    //认证
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
       //在token中获取用户名
        String principal = (String) token.getPrincipal();
        System.out.println(principal);

        //更具身份信息用mybatis查询数据库信息
        if("zhangsan".equals(principal)){
            //参数一:返回数据库中正确用户名
            //参数二:返回数据库中的密码
            //参数散:提供当前realm的名字 this.getName();
            SimpleAuthenticationInfo simpleAuthenticationInfo =
                    new SimpleAuthenticationInfo(principal,"123456",this.getName());
            return simpleAuthenticationInfo;
        }
        return null;
    }
}

  • 创建 TestCustomerRealmAuthentocator
public class TestCustomerRealmAuthentocator {
    public static void main(String[] args) {
        //创建defaultSecurityManager
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();

        //设置自定义realm
        defaultSecurityManager.setRealm(new CustomerRealm());

        //将安全工具类设置defaultSecurityManager
        SecurityUtils.setSecurityManager(defaultSecurityManager);

        //获取subject
        Subject subject = SecurityUtils.getSubject();

        //创建令牌
        UsernamePasswordToken token = new UsernamePasswordToken("zhangsan","123456");

        try {
            subject.login(token);
            System.out.println("登录成功");
        } catch (IncorrectCredentialsException e) {
            e.printStackTrace();
            System.out.println("密码不正确");
        } catch (UnknownAccountException e){
            e.printStackTrace();
            System.out.println("用户名不正确");
        }
    }
}

  • 测试

在这里插入图片描述

shiro基础三:MD5

  • 创建TestMD5
public class TestMD5 {
    public static void main(String[] args) {
        //创建一个md5算法
        Md5Hash md5Hash  = new Md5Hash("123456");
        System.out.println(md5Hash);

        //使用md5加盐
         Md5Hash md5Hash1 = new Md5Hash("123456","qwea");
         System.out.println(md5Hash1);

         //md5+salt+hash散列
        Md5Hash md5Hash2 = new Md5Hash("123456", "qwea", 123);
        System.out.println(md5Hash2);
    }
}

在这里插入图片描述

  • 创建 CustomerMd5Realm继承AuthorizingRealm
//授权
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        return null;
    }

    //认证
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        String principal = (String)token.getPrincipal();
        if("zhangsan".equals(principal)){
           return new SimpleAuthenticationInfo(
                   principal,
                   "4d28cf9e49d3cf8ae8fe8fea9437ea3f", //MD5+随机盐+散列后的密码
                   ByteSource.Util.bytes("qwea"),//随机盐
                   this.getName());
        }
        return null;
    }
}

  • 创建 TestCustomerMd5RealmAuthenicator
 public static void main(String[] args) {
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
        CustomerMd5Realm realm = new CustomerMd5Realm();

        //设置realm使用hash凭证匹配器
        HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
        credentialsMatcher.setHashAlgorithmName("md5");
        credentialsMatcher.setHashIterations(123); //告诉凭证匹配器散列多少次
        realm.setCredentialsMatcher(credentialsMatcher);

        defaultSecurityManager.setRealm(realm);
        SecurityUtils.setSecurityManager(defaultSecurityManager);
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken("zhangsan","123456");

        try {
            subject.login(token);
            System.out.println("登录成功");
        } catch (IncorrectCredentialsException e) {
            e.printStackTrace();
            System.out.println("密码不正确");
        } catch (UnknownAccountException e){
            e.printStackTrace();
            System.out.println("用户名不正确");
        }
    }
}

在这里插入图片描述

2,shiro授权

在这里插入图片描述

关键对象

在这里插入图片描述

授权过程

在这里插入图片描述

授权方式

在这里插入图片描述

权限字符串

在这里插入图片描述

授权编码

在这里插入图片描述

开发授权

  • 修改CustomerRealm类
public class CustomerRealm extends AuthorizingRealm {

    //授权
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        System.out.println("============");
        String primaryPrincipal = (String)principals.getPrimaryPrincipal();
        System.out.println("身份信息:"+primaryPrincipal);
        //根据身份信息,在数据库中获取当前角色信息

        //将数据库中查询的角色信息复制给权限对象
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        simpleAuthorizationInfo.addRole("admin");
        simpleAuthorizationInfo.addRole("user");

        //将数据库中查询权限信息赋值给权限对象
        simpleAuthorizationInfo.addStringPermission("user:*:01");
        simpleAuthorizationInfo.addStringPermission("product:create");
        return simpleAuthorizationInfo;
    }

    //认证
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
       //在token中获取用户名
        String principal = (String) token.getPrincipal();
        System.out.println(principal);

        //更具身份信息用mybatis查询数据库信息
        if("zhangsan".equals(principal)){
            //参数一:返回数据库中正确用户名
            //参数二:返回数据库中的密码
            //参数散:提供当前realm的名字 this.getName();
            SimpleAuthenticationInfo simpleAuthenticationInfo =
                    new SimpleAuthenticationInfo(principal,"123456",this.getName());
            return simpleAuthenticationInfo;
        }
        return null;
    }
}

  • 编写TestCustomerRealmAuthentocator类
public class TestCustomerRealmAuthentocator {
   public static void main(String[] args) {
       //创建defaultSecurityManager
       DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();

       //设置自定义realm
       defaultSecurityManager.setRealm(new CustomerRealm());

       //将安全工具类设置defaultSecurityManager
       SecurityUtils.setSecurityManager(defaultSecurityManager);

       //获取subject
       Subject subject = SecurityUtils.getSubject();

       //创建令牌
       UsernamePasswordToken token = new UsernamePasswordToken("zhangsan","123456");

       try {
           subject.login(token);
           System.out.println("登录成功");
       } catch (IncorrectCredentialsException e) {
           e.printStackTrace();
           System.out.println("密码不正确");
       } catch (UnknownAccountException e){
           e.printStackTrace();
           System.out.println("用户名不正确");
       }

       //认证用户进行授权
       if(subject.isAuthenticated()){
           //基于单角色进行权限授权
           System.out.println(subject.hasRole("admin"));

           //基于多角色的权限控制
           System.out.println(subject.hasAllRoles(Arrays.asList("admin","user")));

           //是否有其中一个角色
           boolean[] booleans = subject.hasRoles(Arrays.asList("admin", "user", "student"));
           for(boolean aBoolean : booleans){
               System.out.println(aBoolean);
           }

           //基于权限支付窜的访问控制, 资源标识符:操作:资源类型
           System.out.println("基于权限支付窜的访问控制:"+subject.isPermitted("user:update:01"));
           System.out.println("基于权限支付窜的访问控制:"+subject.isPermitted("product:create:01"));

           //分别具有那些权限
           boolean[] permitted = subject.isPermitted("user:*:01", "order:*:10");
           for(boolean b : permitted){
               System.out.println(b);
           }

           //同时具有那些权限
           boolean permittedAll = subject.isPermittedAll("user:*:01", "product:*");
           System.out.println(permittedAll);

       }
   }
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值