Apache Shiro 体系结构
Apache Shiro的设计目标就是用直观且易于使用的方式,来简化应用的安全性,Shiro的核心设计是基于在某人(或某物)与应用程序交互的上下文中的
软件应用经常是基于用户故事设计的,也就是说基于用户与软件交互的方式来设计用户界面或服务API,比如在用户登录后给用户展示一个个人信息按钮,用户未登录时展示一个登录按钮。应用程序的代码都是用于满足用户的需求的,即使这个所谓的“用户”是另一个软件系统
Shiro在自己的设计中体现了这些概念,实际上,Apache Shiro在任何应用程序中都保持直观和易于使用的特点
概览
概括的说,Shiro有3个主要的概念,Subject,SecurityManager和Realms,下图展示了他们之间的关系
- Subject:正如之前提到的,Subject是当前执行的用户所拥有的特定于安全的视图,“User”的概念经常和人绑定,而Subject可以使人,也可以是第三方服务,等等与软件交互的任何事务。Subject实例都绑定到SecurityManager,与Subject交互时,这些交互转化为与SecurityManager的特定于Subject的交互。
- SecurityManager:SecurityManager是Shiro体系结构的核心,它协调其内部安全组件,形成一个对象图。一旦SecurityManager和它的内部对象图配置完成,通常就不在需要和SecurityManager打交道,开发人员更多的是和Subject 的 API 打交道。之后会详细介绍SecurityManager的细节内容,需要注意的是,Subject上的所有操作,背后都是SecurityManager在进行工作的
-
Realms:Realms是Shiro和应用安全数据的桥梁,当需要与用户帐户安全相关的数据进行实际交互以执行身份验证(登录)和授权(访问控制)时,Shiro将会从事先配置好的Realms中获取数据。
- Realms相当于安全方面的DAO,它封装了与数据源的连接等细节,为Shiro提供需要的数据。在配置Shiro时,必须至少配置一个Realm用于认证和授权,也就是说,SecurityManager至少需要一个Realm
- Shiro提供了一些开箱即用的Realms,来连接各个数据源,如LDAP,关系型数据库,文本文件如INI配置文件等等,如果默认的Realm不能满足需求,也可以实现自己的Realm来自定义数据源
- 与其他内部组件一样,Shiro的SecurityManager从Realms获取以Subject实例表示的身份数据
详细架构
下图展示了Shiro的具体核心架构
-
Subject——org.apache.shiro.subject.Subject
特定于当前与软件交互的实体的安全视图
-
SecurityManager——org.apache.shiro.mgt.SecurityManager
Shiro架构的核心,管理并协调各个组件共同完成安全工作,它还管理每个应用程序用户的Shiro视图,因此它知道如何为每个用户执行安全操作。
-
Authenticator——org.apache.shiro.authc.Authenticator
Authenticator是负责认证的组件,当用户尝试登录时,登录是由Authenticator来执行的,Authenticator将会从Realms取出用户信息,来和用户提供的登录信息进行比对
-
Authenticator Strategy——org.apache.shiro.authc.pam.AuthenticationStrategy
如果超过一个Realm被配置了,这个AuthenticationStrategy将会协调这些Realms来决定认证操作是否成功,比如,认证成功是需要所有的Realms都认证成功,还是仅仅一个Realm成功
-
-
Authorizer——org.apache.shiro.authz.Authorizer
Authorizer是负责访问控制的组件,换句话说,它负责检测用户是否有执行某个操作的权限。和Authenticator一样,Authorizer也从多个Realms数据源中获取用户的角色信息和权限信息,通过这些信息来判断用户是否可以执行某个操作
-
SessionManager——org.apache.shiro.session.mgt.SessionManager
注意不是SecurityManager,SessionManager负责创建和管理用户的Session周期。在安全框架中,Shiro提供了一个独有的特性,Shiro可以在任何环境中管理用户会话,即使实在非Web/Servlet和非EJB容器环境中,默认情况下,Shiro将会使用已有的会话机制,如Servlet容器,如果没有,Shiro将会使用内建的企业会话管理机制来管理会话。通过SessionDao,我们可以使用任何数据源来持久化Session
-
SessionDAO——org.apache.shiro.session.mgt.eis.SessionDAO
SessionDAO代表SessionManager执行会话持久性(CRUD)操作。它允许将任何数据存储插入到Session Management基础结构中
-
-
CacheManager——org.apache.shiro.cache.CacheManager
CacheManager负责创建Shiro中的其他组件的Cache实例并管理其生命周期,因为Shiro需要访问各种数据源来进行认证,授权和会话管理,缓存一直是框架中的一流架构特性,可以在使用这些数据源时提高性能,任何现代的开源或者企业缓存产品都可以接入Shiro中
-
Cryptography——org.apache.shiro.crypto.*
Shiro的crypto包包含了易于使用和理解的常见加密算法实现。使用过Java自带的加密库的人都应该知道它很难使用,Shiro提供的加密API简化了复杂的Java机制,让加密更便于使用
-
Realms——org.apache.shiro.realm.Realm
正如前面提到的,Realms是Shiro和应用程序数据的桥梁,当需要执行认证和授权时,Shiro会从至少一个Realm中寻找用户信息,应用程序中可以配置许多个Realm,Shiro会在必要时协调这些Realm
SecurityManager
Shiro的API提倡以Subject为中心的编程方式,因此大多数的开发者很少会和SecurityManager直接接触,但是,仍然有必要去了解SecurityManager如何进行工作,尤其是为应用程序配置SecurityManager的时候
SecurityManager 相关设计
SecurityManager主要负责执行安全操作和管理所有应用程序用户的状态,在Shiro的默认视线中,它包括以下功能:
- 认证
- 授权
- 会话管理
- 缓存管理
- 协调Realm
- 事件传播
- “记住我”服务
- 创建Subject
- 登录等等功能
但是在单个组件中要管理的功能太多了。而且,如果所有的东西都集中到一个实现类中,那么使这些东西变得灵活和可定制将是非常困难的。为了简化配置,让配置变得灵活,Shiro进行了高度的模块化实现,即SecurityManager的实现更多是扮演了一个轻量级的容器组件,将所有的行为委托给它拥有的组件
当组件执行它们的逻辑的时候,SecurityManager知道在何时,如何去协调这些组件以达到正确的行为。SecurityManager的实现和它的组件都是兼容JavaBean的,也就是说,可以通过JavaBean的方式来配置它们,如Spring等等