Subject 本质上是当前运行用户特定的’View’(视图),而单词“User”经常暗指一个人,Subject 可以是一个人,但也可以是第三方服务、守护进程帐户、时钟守护任务或者其它–当前和软件交互的任何事件。 Subject 实例都和(也需要)一个 SecurityManager 绑定,当你和一个Subject 进行交互,这些交互动作被转换成 SecurityManager 下Subject 特定的交互动作。
Subject 类图
Subject
主要分为两类,一种是在非 Web 环境下使用,另一种是在 Web 环境下使用,包含了 java Servlet
相关的信息。Subject
的整个类图如下所示:
Subject
最为最顶层的接口,定义了用户基本信息的接口、登录相关和权限相关的接口。
DelegatingSubject
实现了Subject
接口,在非 Web 环境下使用。
WebDelegatingSubject
则是在 Web 环境下使用,需要依赖于Servlet
。
RequestPairSource
提供当前正在执行的请求关联的ServletRequest ServletRequest
和ServletResponse ServletResponse
对
Subject 实例化
工厂类 SubjectFactory
SubjectFactory
接口时负责创建并且初始化Subject
1 | public interface SubjectFactory { |
它有两个子类,DefaultSubjectFactory
使用在非 Web 环境下,会创建DelegatingSubject
实例。DefaultWebSubjectFactory
则对应在 Web 环境下,会创建WebDelegatingSubject
实例。
1 | public Subject createSubject(SubjectContext subjectContext) { |
初始化参数 SubjectContext
SubjectContext
用于初始化Subject
的,不同的子类对应着不同类型的Subject
。比如下面的DefaultSubjectContext
用作非 Web 环境下的DelegatingSubject
初始化,而DefaultWebSubjectContext
用于 Web 环境下的WebDelegatingSubject
初始化。
SubjectContext
提供了SecurityManager
、Session
、身份凭证AuthenticationToken
、身份信息AuthenticationInfo
、客户端 ip 等参数。
DefaultSubjectContext
实现了SubjectContext
接口,它相当于JavaBean
,是上述这些信息的集合类。
DefaultSubjectContext
只是在DefaultSubjectContext
基础之上,添加了ServletRequest
和ServletResponse
的操作。
1 | //Subject中 Builder类的构造,此时SubjectContext就是在此时构造的 |
我们来看下非web模式下Subject构造:
1 | public Subject createSubject(SubjectContext context) { |
Subject 实例化
1、spring BeanPostProcessor(项目启动)安全管理器来源
1 | // 看到这我们就很明白了setSecurityManager是什么时候设置进来的了 |
2、shiro过滤器(请求前)
在AbstractShiroFilter中
1 | protected void doFilterInternal(ServletRequest servletRequest, ServletResponse servletResponse, final FilterChain chain) |
Subject 持久化
SubjectDAO
接口定义了Subject
的持久化
1 | public interface SubjectDAO { |
目前只有一个实现类DefaultSubjectDAO
,它的原理也比较简单,使用了 session 存储信息。它只是存储了用户的身份信息和是否已经成功认证。
session 属性名 | 类型 | 含义 |
---|---|---|
DefaultSubjectContext.AUTHENTICATED_SESSION_KEY |
PrincipalCollection |
身份列表(一个用户可能有多个身份) |
DefaultSubjectContext.AUTHENTICATED_SESSION_KEY |
Boolean | 是否通过身份认证 |
login 原理
现在我们来看看从Subject.login
方法开始,看看整个 login 的过程。Subject
的login
方法只有DelegatingSubject
子类实现了,它只是将请求转发给DefaultSecurityManager
处理。
1 | public class DefaultSecurityManager extends SessionsSecurityManager { |
再继续看看Subject
的创建过程
1 | public class DefaultSecurityManager extends SessionsSecurityManager { |
上面调用了两个方法doCreateSubject
和save
方法,最后来看看它们的原理
1 | public class DefaultSecurityManager extends SessionsSecurityManager { |
整个 login 流程如下图所示:
1 | sequenceDiagram |
logout 原理
在执行Subject.logout
方法完成登出操作后,shrio 会将Subject
的信息都设置为空,并且会删除关联的 session。
参考
1 | https://blog.csdn.net/qq_34021712/article/details/80418112 |
- 本文作者: 初心
- 本文链接: http://funzzz.fun/2021/02/03/Apache Shiro --- 3 subject/
- 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!