zoukankan      html  css  js  c++  java
  • shiro学习笔记1:shiro简单使用

    shiro是什么?

    shiro:安全框架

    Apache Shiro是一个功能强大且灵活的开源安全框架,可以清晰地处理身份验证,授权,企业会话管理和加密。

    Apache Shiro的首要目标是易于使用和理解。安全有时可能非常复杂,甚至是痛苦的,但事实并非如此。框架应尽可能掩盖复杂性,并提供简洁直观的API,以简化开发人员确保其应用程序安全的工作。

    以下是Apache Shiro可以做的一些事情:

    • 验证用户以验证其身份
    • 为用户执行访问控制,例如:
      • 确定是否为用户分配了某个安全角色
      • 确定是否允许用户执行某些操作
    • 在任何环境中使用Session API,即使没有Web容器或EJB容器也是如此。
    • 在身份验证,访问控制或会话生命周期内对事件做出反应。
    • 聚合用户安全数据的1个或多个数据源,并将其全部显示为单个复合用户“视图”。
    • 启用单点登录(SSO)功能
    • 无需登录即可为用户关联启用“记住我”服务
      ...... 
      以及更多 - 全部集成到一个易于使用的内聚API中。

    Shiro尝试为所有应用程序环境实现这些目标 - 从最简单的命令行应用程序到最大的企业应用程序,而不会强制依赖其他第三方框架,容器或应用程序服务器。当然,该项目旨在尽可能地融入这些环境,但它可以在任何环境中开箱即用。

    shiro的功能?

    Apache Shiro是一个具有许多功能的综合应用程序安全框架。下图显示了Shiro关注其能量的位置,此参考手册将以类似方式组织:

    Shiro针对Shiro开发团队所称的“应用程序安全的四大基石” - 身份验证,授权,会话管理和加密:

    • 身份验证:有时称为“登录”,这是证明用户是他们所说的人的行为。

    • 授权:访问控制的过程,即确定“谁”可以访问“什么”。

    • 会话管理:即使在非Web或EJB应用程序中,也可以管理特定于用户的会话。

    • 密码学:使用加密算法保持数据安全,同时仍然易于使用。

    还有其他功能可以在不同的应用程序环境中支持和强化这些问题,尤其是:

    • Web支持:Shiro的Web支持API可帮助轻松保护Web应用程序。
    • 缓存:缓存是Apache Shiro API中的第一层公民,可确保安全操作保持快速高效。
    • 并发:Apache Shiro支持具有并发功能的多线程应用程序。
    • 测试:存在测试支持以帮助您编写单元和集成测试,并确保您的代码按预期受到保护。
    • “运行方式”:允许用户假定其他用户的身份(如果允许)的功能,有时在管理方案中很有用。
    • “记住我”:记住用户在会话中的身份,因此他们只需要在必要时登录。

    以上内容引自官网

    为什么要使用shiro?

    在之前的介绍中,已经对shiro框架有了简单的了解,大概知道了shiro的主要功能,shiro是一个框架,框架的主要功能就是方便开发人员,简化代码量,而且shiro是一个安全框架,在使用shiro框架之前,我们写一个web项目,虽然可以通过各种方式添加用户权限,根据不同角色不同权限分配不同的功能,以及登录验证等,但是这种情况只是我们客观的不提供其他资源的连接地址给用户,用户无法点击直接访问,如果用户直接在浏览器上输入其他资源地址,那么可能没有访问权限的资源也可以访问,这是安全行问题,因此就需要处理,我们可以设置拦截器、过滤器等进行验证,但是如果项目很大的话,可能会有很多的资源,对应很多的地址,如果每个地址都设置一个拦截器,那也是一个很大的工作量,因此shiro框架就建少了我们的代码量,将重心放在业务逻辑的处理上。

    使用shiro的好处,在之前的介绍中已经涉及,不在赘述

    shiro架构图分析

    shiro的框架架构图如下:

    我们根据这个架构图来进行分析:

    subject(主题):当前与软件交互的实体的特定于安全性的视图(也就是发送请求的视图)

    Security Manager(安全管理器):shiro框架的核心部分,所有的subject都发送到这里进行处理,它主要是一个“伞形”对象,协调其托管组件,以确保它们一起平稳运行。它还管理Shiro对每个应用程序用户的视图,因此它知道如何对每个用户执行安全操作

    Authenticator(认证器):是负责执行验证用户信息的组件。当用户尝试登录时,就会执行该认证器,认证器知道如何协调从一个或多个领域中获取用户信息的数据,从这些数据中获取的数据Realms用于验证用户的身份,以保证用户确实是他们所说的人。

      AuthenticationStrategy(身份验证策略):如果Realm配置了多个,AuthenticationStrategy则将协调领域以确定身份验证尝试成功或失败的条件(例如,如果一个领域成功    但其他领域失败尝试是否成功?必须所有领域成功吗?只有第一个?)。

    Authorizer(授权方):该组件用来说明是否允许用户做某事,Authorizer也知道如何协调多个后端数据源以访问角色和权限信息。Authorizer使用该信息来确定到底是否允许用户执行特定的操作。

    SessionManager(会话管理器):该组件知道如何创建和管理用户Session生命周期,提供在所有环境中的用户强大的会话体验。这是安全框架领域的一项独特功能 - 即使没有可用的Web / Servlet或EJB容器,Shiro也能够在任何环境中管理本地用户Sessions。默认情况下,Shiro将使用现有的会话机制(例如Servlet容器),但如果没有,例如在独立应用程序或非Web环境中,它将使用其内置的企业会话管理提供相同的编程经验。

      SessionDAO(会话的增删改查使用sessionDAO来处理会话管理器中会话的CURD操作

    CacheManager(缓存管理器):创建和管理Cache其他四个组件使用实例的生命周期。由于Shiro可以访问许多后端数据源以进行身份​​验证,授权和会话管理,因此缓存一直是框架中的一流架构功能,可在使用这些数据源时提高性能。任何现代开源和/或企业缓存产品都可以插入Shiro,以提供快速有效的用户体验。

    Cryptography(密码加密):密码加密是企业安全框架的自然补充。Shiro的crypto软件包包含易于使用和理解的密码加密,哈希(aka摘要)和不同编解码器实现的表示。该软件包中的所有类都经过精心设计,易于使用且易于理解。Shiro的加密API简化了复杂的Java机制,使加密更加容易使用。

    Realm(领域):Realms充当Shiro与应用程序安全数据之间的“桥接”或“连接器”。当实际与安全相关数据(如用户帐户)进行交互以执行身份验证(登录)和授权(访问控制)时,Shiro会从为应用程序配置的一个或多个领域中查找许多这些内容。您可以根据Realms需要配置任意数量(通常每个数据源一个),Shiro将根据需要进行身份验证和授权协调。

    引自官网 ,可以查看原文

    shiro的简易使用:

    需要导入jar包:

    需要导入日志文件jar包,以及日志文件:

    log4j.rootLogger=INFO, stdout
    
    log4j.appender.stdout=org.apache.log4j.ConsoleAppender
    log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
    log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m %n
    
    # General Apache libraries
    log4j.logger.org.apache=WARN
    
    # Spring
    log4j.logger.org.springframework=WARN
    
    # Default Shiro logging
    log4j.logger.org.apache.shiro=TRACE
    
    # Disable verbose logging
    log4j.logger.org.apache.shiro.util.ThreadContext=WARN
    log4j.logger.org.apache.shiro.cache.ehcache.EhCache=WARN

    使用shiro.ini配置文件作为用户信息的数据源:

    # -----------------------------------------------------------------------------
    # 配置用户信息
    # -----------------------------------------------------------------------------
    [users]
    # 格式:用户root,密码为:secret,角色为admin
    root = secret, admin
    guest = guest, guest
    presidentskroob = 12345, president
    darkhelmet = ludicrousspeed, darklord, schwartz
    lonestarr = vespa, goodguy, schwartz
    
    # -----------------------------------------------------------------------------
    # 配置角色信息
    # -----------------------------------------------------------------------------
    [roles]
    # admin拥有所有的权限
    admin = *
    # The 'schwartz' role can do anything (*) with any lightsaber:
    schwartz = lightsaber:*
    # The 'goodguy' role is allowed to 'drive' (action) the winnebago (type) with
    # license plate 'eagle5' (instance specific id)
    goodguy = winnebago:drive:eagle5
    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.session.Session;
    import org.apache.shiro.subject.Subject;
    import org.apache.shiro.util.Factory;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    
    public class Quickstart {
    
        private static final transient Logger log = LoggerFactory.getLogger(Quickstart.class);
    
    
        public static void main(String[] args) {
    
            /*创建安全管理器实例*/
            Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
            SecurityManager securityManager = factory.getInstance();
    
            /*为SecurityUtils工具类注入该安全管理器*/
            SecurityUtils.setSecurityManager(securityManager);
    
            /*获取当前操作视图的用户*/
            Subject currentUser = SecurityUtils.getSubject();
    
            // 尝试在不适用web容器的情况下使用session会话
            Session session = currentUser.getSession();
            session.setAttribute("user", "张三");
            String value = (String) session.getAttribute("user");
            if (value.equals("张三")) {
                log.info("Retrieved the correct value! [" + value + "]");
            }
    
            // 登录测试
            if (!currentUser.isAuthenticated()) {
                /**
                 *  输入账号密码生成身份令牌
                 */
                UsernamePasswordToken token = new UsernamePasswordToken("root", "secret");
                //记住我
                token.setRememberMe(true);
                try {
                    currentUser.login(token);
                } catch (UnknownAccountException uae) {
    //                找不到用户
                    log.info("There is no user with username of " + token.getPrincipal());
                } catch (IncorrectCredentialsException ice) {
    //                密码错误
                    log.info("Password for account " + token.getPrincipal() + " was incorrect!");
                } catch (LockedAccountException lae) {
    //                账户锁定
                    log.info("The account for username " + token.getPrincipal() + " is locked.  " +
                            "Please contact your administrator to unlock it.");
                }
                // ... catch more exceptions here (maybe custom ones specific to your application?
                catch (AuthenticationException ae) {
                    //unexpected condition?  error?
                }
            }
    
            //输出登录者信息
            log.info("User [" + currentUser.getPrincipal() + "] logged in successfully.");
    
            //测试该用户的角色:
            if (currentUser.hasRole("schwartz")) {
                log.info("May the Schwartz be with you!");
            } else {
                log.info("Hello, mere mortal.");
            }
    
            if (currentUser.isPermitted("lightsaber:weild")) {
                log.info("You may use a lightsaber ring.  Use it wisely.");
            } else {
                log.info("Sorry, lightsaber rings are for schwartz masters only.");
            }
    
            if (currentUser.isPermitted("winnebago:drive:eagle5")) {
                log.info("You are permitted to 'drive' the winnebago with license plate (id) 'eagle5'.  " +
                        "Here are the keys - have fun!");
            } else {
                log.info("Sorry, you aren't allowed to drive the 'eagle5' winnebago!");
            }
    
            //a注销!
            currentUser.logout();
    
            System.exit(0);
        }
    }
  • 相关阅读:
    Android Studio连接真机
    day 4 __all__ 包 __init__.py
    day1 创建X00001文件1K
    day 3 模块
    day 2 异常传递 ,抛出
    day 1 异常基本功能
    day 7 __new___
    day 6 汽车4S店铺
    day 5 多态 类 静态
    day 4 继承
  • 原文地址:https://www.cnblogs.com/Zs-book1/p/11341102.html
Copyright © 2011-2022 走看看