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