前言
从前篇 shiro 架构文章中,可以了解到 SecurityManager 是 shrio 框架中最核心的部分,它作连接了认证,权限,session 多个模块。本篇文章会介绍 SecurityManager 的设计思想,和多个模块之间的衔接。
设计模式
SecurityManager 的设计使用了门面模式,如下图所示:
SecurityManager 作为门面类,封装下面的多个子模块。
SecurityManager 类图
再来看看它的类图设计:
classDiagram
class Authenticator
<<interface>> Authenticator
class Authorizer
<<interface>> Authorizer
class SessionManager
<<interface>> SessionManager
class SecurityManager
<<interface>> SecurityManager
Authenticator <|-- SecurityManager
Authorizer <|-- SecurityManager
SessionManager <|-- SecurityManager
class Destroyable
<<interface>> Destroyable
class CacheManagerAware
<<interface>> CacheManagerAware
class EventBusAware
<<interface>> EventBusAware
class CachingSecurityManager
<<abstract>> CachingSecurityManager
Destroyable <|-- CachingSecurityManager
CacheManagerAware <|-- CachingSecurityManager
EventBusAware <|-- CachingSecurityManager
class RealmSecurityManager
<<abstract>> RealmSecurityManager
SecurityManager <|-- CachingSecurityManager
CachingSecurityManager <|-- RealmSecurityManager
class AuthenticatingSecurityManager
<<abstract>> AuthenticatingSecurityManager
RealmSecurityManager <|-- AuthenticatingSecurityManager
class AuthorizingSecurityManager
<<abstract>> AuthorizingSecurityManager
AuthenticatingSecurityManager <|-- AuthorizingSecurityManager
class SessionsSecurityManager
<<abstract>> SessionsSecurityManager
AuthorizingSecurityManager <|-- SessionsSecurityManager
class DefaultSecurityManager
SessionsSecurityManager <|-- DefaultSecurityManager
class DefaultWebSecurityManager
DefaultSecurityManager <|-- DefaultWebSecurityManager
上图虽然涉及到了多个类,层级比较多,但是它的设计思想不难。首先注意到最上层的SecurityManager接口,它继承了三个接口,
Authenticator,身份认证Authorizer,权限认证SessionManager,session 管理
然后继续看下面的子类,每一个子类都实现了特定的接口。
AuthenticatingSecurityManager层实现了Authenticator接口,支持用户身份认证。AuthorizingSecurityManager层实现了Authorizer接口,支持权限验证。SessionsSecurityManager层实现了SessionManager接口,支持 session,注意到这里session不仅仅包含web的session。
这三个类都是用了策略模式,来实现对应的接口。以AuthenticatingSecurityManager为例,它实现了Authenticator接口,但都是转发给别的Authenticator实例完成,如下图所示
下面是AuthenticatingSecurityManager实现的代码
|
|
DefaultSecurityManager是 shiro 默认的实现类。
DefaultWebSecurityManager用于在 Web 环境下,增加了 http 的操作。
身份认证模块
身份认证作为 shiro 最基础的模块,这里需要讲述下它的原理和如何集成到 SecurityManager。
Authenticator 接口
认证接口由Authenticator接口表示
|
|
Authenticator也有多个子类:
classDiagram
class Authenticator
<<Interface>> Authenticator
class AbstractAuthenticator
<<abstract>> AbstractAuthenticator
Authenticator <|-- AbstractAuthenticator
class ModularRealmAuthenticator
AbstractAuthenticator <|-- ModularRealmAuthenticator
AbstractAuthenticator抽象类,支持认证成功和失败时的回调。这里需要重要的介绍下ModularRealmAuthenticator子类,它作为 shrio 默认的实现类,并且负责连接着DefaultSecurityManager和Realm。
ModularRealmAuthenticator有个重要的功能,能支持不同的认证策略。举个例子,小明既是公司A的技术总监,同时也是公司B的技术总监,并且两个公司有着独立的身份认证。
现在小明登录到一个系统,这个系统要求只要是技术总监身份,就可以登录,那么认证策略为至少一次认证成功。
如果该系统要求必须是两个公司的技术总监身份,才能登录,那么认证策略为全部都要成功。
shrio 目前支持的策略如下所示:
| 认证策略类 | 含义 | |
|---|---|---|
AtLeastOneSuccessfulStrategy |
会进行所有的身份认证,并聚集认证结果(默认策略) | |
AllSuccessfulStrategy |
必须全部认证成功 | |
FirstSuccessfulStrategy |
只使用第一个身份认证成功的结果,并且支持自定义退出认证链 |
继续来看看ModularRealmAuthenticator的内部,它管理者多个身份认证,这个就是Realm接口,在后面会介绍。下面的代码可以看到它有一个列表来保存Realm
|
|
集成 Authenticator
我们再回到SecurityManager,看看它是如何与ModularRealmAuthenticator集成的。这里通过查看SecurityManager的两个子类就可以知道。
首先RealmSecurityManager支持设置Realm列表,注意到afterRealmsSet函数的调用。
|
|
然后看看AuthenticatingSecurityManager的实现
|
|
权限校检
权限校检同样作为 shiro 最基础的模块,这里也需要讲述下它的原理和如何集成到 SecurityManager。
Authorizer 接口
权限校检接口由Authorizer接口表示,下面列举它的一些方法
|
|
Authorizer也有一个很重要的子类ModularRealmAuthorizer,作为 shrio 默认的实现类,同样管理着多个权限校检。
|
|
注意到上述的权限校检,这里同身份认证不同,只支持一种策略,那就是只要匹配其中的一个权限校检,就认为权限校检成功。
集成 SecurityManager
我们来看看它与SecurityManager集成原理,是由AuthorizingSecurityManager类负责的。
|
|