Apache Shiro 是一个强大且易用的 Java 安全框架,能够让开发者以非常清晰的方式处理身份认证、授权、会话管理以及密码加密。使用其易于理解的 API,开发者可以轻松,高效的为任何应用程序,从最小的移动应用程序到大型的网络和企业应用程序添加安全管理功能。
什么是 Shiro
Apache Shiro 是一个使用 Java 开发的,易于使用,功能强大且灵活的开源安全框架,它为开发人员提供了直观简洁的 API 来支持应用程序中的四个安全性基石:
- 身份验证(Authentication)
- 授权(Authorization)
- 会话管理(Session Management)
- 加密(Cryptography)
Shiro 提供了许多重要且实用的安全性相关的功能,其中被关注得最多的是身份验证和授权功能,这两者也是一个安全框架的核心功能,我们的课程将会把重心放在这两个部分,对于其它部分只进行简单的介绍。
想象有如下的动态安全模型:
管理员可以为应用系统创建不同的角色,角色可以绑定一组权限,之后管理员可以为不同用户分配一个或多个角色,并在应用正常提供服务期间在后台管理网页中随时更改所有这些功能。
通过使用 Shiro,我们将能够很容易的实现上述功能。
Shiro 框架的体系结构
Shiro 的设计目标是通过直观且易于使用的 API 来简化应用程序安全性相关代码的设计,应用程序安全控制功能的实现往往有着不同的需求场景,Shiro 的核心设计参考了这些用户在大多数情况下都会遇到的需求场景,在这些情况下来考虑 Shiro 的安全性设计。
在 Shiro 框架的最上层,主要有 3 个关键组件相互协作:
Subject
正如上面提到的那样,Subject
本质上是系统用户的一个特定安全 "视图",可以表示会与应用程序交互的任何东西。
Subject
实例都强制绑定到 SecurityManager
上,当我们调用 Subject
的方法时,具体的操作最终都会转交给相关的 SecurityManager
进行处理。
SecurityManager
SecurityManager
是 Shiro 体系结构的核心,它协调着内部的其它安全组件,这些安全组件一起形成一种互相协作支持的关系,共同完成 Shiro 提供的所有功能。对于开发人员而言,一旦为应用程序配置了 SecurityManager,通常就不需要再理会它,我们只需要和 Subject
的 API 进行交互就可以了,这在上面的流程图中也有清晰的体现。
Realm
Realm
是 Shiro 与应用程序数据之间交换的“桥梁”,当 Shiro 真正需要与安全性相关的数据(例如用户帐户,用户角色,权限等)进行交互以执行身份验证和授权时,Shiro 会从一个或多个为应用程序配置的 Realm
中查找这些数据。
可以简单地把 Realm
理解为特定于安全性的 DAO
,它封装了对安全性相关数据的访问,在配置 Shiro 时,我们必须至少指定一个 Realm
以用于身份验证(或授权)。
详细架构
下图展示了 Shiro 的核心体系结构:
上图是一个更加具体的 Shiro 详细架构图,图中清晰地描述了 Subject
,Security Manager
和 Realm
三者各自在整个 Shiro 框架中所扮演的角色,以及担负的职责。
为了简化配置和实现灵活的可配置性(可插拔性),Shiro 的实现都是高度模块化的,高度模块化使得 SecurityManager
的实现实际上并没有做实质性的事情。相反,SecurityManager
的作用是作为一个轻量级的“容器”组件,将几乎所有的行为委托给封装在内部的其它组件,这是“包装器”设计模式的一种使用。
下面对身份认证器(Authenticator
)和访问控制器(Authorizer
)进行简单说明。
身份认证器(Authenticator
)是负责执行和响应用户认证(登录)的组件。当用户尝试登录时,该逻辑由 Authenticator
执行,Authenticator
知道如何与一个或多个 Realm
进行协调,从这些 Realm
中获取用户的身份信息,然后完成身份认证过程。
访问控制器(Authorizer
)是负责决定用户对应用中具体资源能否访问和操作的组件,是最终决定用户是否被允许做某事的机制,与 Authenticator
一样,Authorizer
也知道如何与多个 Realm
协调,以获取角色和权限信息,Authorizer
使用这些信息来确定用户是否被允许执行某个动作。
以上内容来自实验楼新课《Shiro 与 Spring Boot 实现权限管理系统》,课程后续还有:
该门课程将会以理论学习与实战相结合的方式分别对 Shiro 的身份认证和授权这两个最重要的安全功能着重进行学习。下面的截图展示了实战学习中,开发完成后角色管理的部分接口: