前言
从前篇 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
类负责的。
|
|