本文转载自微信公众号《程序新视界》,作者二师兄丑胖子。转载本文请联系程序新视界公众号。在实践中,我发现很多朋友虽然都在使用Shiro,但是他们好像并没有意识到。有些项目甚至使用过滤器来实现权限管理,网上的相关教程比较老。所以,我决定更新这样一个关于Shiro的系列教程给大家,最后整理成书分享给大家。如果你也想了解更多Shiro框架,那就关注公众号《程序新视野》,可以及时获取最新文章,本系列更新时会整理成电子文档分享尽快和你在一起。第一篇给大家科普一些基本概念,下面开始正文。前言权限管理是每一个系统都不可或缺的,它属于系统安全的范畴,实现对用户访问系统的控制,按照规定的安全策略控制用户对资源的访问。权限管理通常包括用户身份认证和授权两部分,简称认证授权。对于需要访问控制的资源,首先要进行用户身份认证。认证通过后,用户可以访问具有访问权限的资源。对于权限管理,在Java系统中,常见的权限框架有Shiro和SpringSecurity。当然,在一些简单或古老的系统中,可能仍然会使用手写过滤器来管理和控制权限。本文首先从Shiro的功能、组件、架构等方面向大家介绍Shiro框架。Shiro简介ApacheShiro是一个功能强大且易于使用的Java安全框架,可执行身份验证、授权、密码和会话管理。与之对应的是SpringSecurity,但在大多数项目中开发者更喜欢使用Shiro来管理权限。主要是使用起来比较简单,而且SpringSecurity比较重量级,学习曲线陡峭,实际环境需要的功能没有SpringSecurity那么多。所以,一般情况下,使用Shiro就足够了。Shiro可以在任何应用程序中快速轻松地使用,从最小的移动应用程序到最大的Web和企业应用程序。Shiro能做什么Shiro提供以下功能:身份验证、授权、加密、会话管理、Web支持、缓存等。可用于保护任何应用程序:从命令行应用程序、移动应用程序到最大的Web和企业应用程序。关于Shiro的核心功能,官方给出了下图:使用Shiro,我们可以实现以下功能:用户认证;用户权限控制:判断用户是否具有特定角色;确定用户是否可以执行操作;在任何环境API中使用Session,即使对于Web或EJB容器之外的应用程序也是如此;可以在身份验证、访问控制和会话期间响应事件;聚合一个或多个用户安全数据的数据源,并将它们全部呈现为单个复合用户“视图”;支持单点登录(SSO)功能;支持登录时“记住”功能;其他应用;Shiro特性Shiro的目标是:在各种应用中(从命令行到大型企业应用),做到任何环境下都可以直接使用,而不需要依赖其他三方框架、容器或应用本身。同时具有以下特点:易于理解的JavaSecurityAPI;简单的身份认证(登录),支持多种数据源(LDAP、JDBC、Kerberos、ActiveDirectory等);简单的角色授权(访问控制),支持细粒度的签名权限;支持一级缓存,提升应用性能;内置基于POJO的企业会话管理,适用于web和非web环境;异构客户端会话访问;非常简单的加密API;不与任何框架或容器捆绑,可独立运行;Shiro各个模块的功能结合下图,我们细化一下Shiro各个模块对应的功能:Authentication:身份认证/登录,验证用户是否有对应的身份;Authorization:授权,即权限验证。验证用户是否具有操作功能的权限。如:验证用户是否具有某种角色,是否有权限操作某种资源;SessionManagement:会话管理,在session中存储用户登录信息,支持web环境和非web环境;密码学:对数据进行加密并使其易于使用例如,密码被加密并存储在数据库中;WebSupport:Web支持,可以轻松集成到Web环境中;Caching:缓存,比如缓存用户信息,用户登录后的角色/权限;并发性:Shiro支持多线程场景下面的并发性验证,即如果一个线程中开启了另一个线程,权限可以自动传播;测试:提供测试支持;RunAs:允许一个用户冒充另一个用户(如果他们允许)访问;记住我:记住我,登录后下次可以直接进入系统。看了上面的组件,是不是突然觉得Shiro在实际应用中被低估了呢?Shiro虽然为我们提供了这么多的功能,但是并没有帮助我们实现用户、权限等具体的系统。关于用户、角色、权限等需要自己设计,然后在Shiro中进行处理。核心组件Shiro包括三个核心组件:Subject、SecurityManager和Realms。这三个组件之间的关系如下图所示:Subject:主体,即“当前操作用户”。在Shiro中,Subject不仅仅是指人,它是一个抽象的概念,也可以是第三方进程、后台账号(DaemonAccount)或者其他类似的东西(比如爬虫、机器人等)。也就是说它只是表示“当前正在与软件交互的东西”。所有的Subject都绑定到SecurityManager上,而SecurityManager才是实际的执行者。SecurityManager:是Shiro框架的核心,典型的Facade模式。Shiro通过SecurityManager管理内部组件实例(包括所有Subject),并通过它提供安全管理的各种服务。类似于SpringMVC中DispatcherServlet的作用。Realm:域,充当Shiro与应用安全数据之间的“桥梁”或“连接器”。也就是说,当对用户进行认证(登录)和授权(访问控制)验证时,Shiro会从应用配置的Realm中查找用户及其权限信息。从这个意义上说,Realm本质上是一个安全相关的DAO:它封装了数据源的连接细节,在需要的时候向Shiro提供相关数据。配置Shiro时,至少指定一个Realm用于身份验证和/或授权。Shiro有一个内置的Realm,可以连接到大量安全数据源(又名目录),例如LDAP、关系数据库(JDBC)、类INI文本配置资源和属性文件。如果默认的Realm不能满足你的需求,你也可以自定义Realm的实现。Shiro架构概述分析了以上组件。下面梳理一下Shiro使用的简单场景:应用使用Subject进行认证授权,Subject委托给SecurityManager进行管理。SecurityManager需要Authenticator和Realm的支持进行认证授权,所以需要在SecurityManager中注入Realm。那么,Shiro的内部架构是怎样的呢?在上图中,我们已经提到了Subject、SecurityManager和Realm。这里再看看其他模块:Authenticator:Authenticator,负责Subject认证,支持自定义实现;AuthenticationStrategy必填,即认证通过的条件。Authrizer:授权者,也就是访问控制器,用于判断主体是否有权限进行相应的操作。SessionManager:SessionManager用于管理Session的生命周期。Shiro既可以在web环境也可以在非web环境下使用,所以Shiro抽象出一个session来管理主体和应用交互的数据,这样就可以集中管理不同应用的session,实现分布式session。SessionDAO:如果要将Session存储在数据库或者Memcached中,可以实现相应的SessionDAO来实现sessionCRUD。在SessionDAO中可以使用Cache进行缓存,提高性能;CacheManager:缓存控制器,用于管理用户、角色、权限等缓存。Cryptography:密码模块提供通用的加密和解密组件。了解了以上各个组件的作用,再回想一下实际中的应用,是不是有点明白了?综上所述,很多朋友在使用shiro的时候,往往会在网上找一段代码,简单修改后使用。但是没有深入探究各个组件之间的关系以及实现这个功能的原理。这样一来,即使实践了很多项目,仍然无法提升自己的技能。本文对shiro的功能、架构、组件等进行了讲解,学习完本文,你一定已经掌握了使用Shiro的基本原理和概念,也为后续的深入学习和实践做好了准备。
