前言
Subject是 我们在 shiro 框架中,第一个介绍的概念。它表示用户,存储了用户身份认证的相关配置信息。除此之外,还支持登录,退出,session 等接口操作。本篇文章会先介绍Subject的种类,然后介绍它是如何创建的,以及登录操作等。
Subject 类图
Subject主要分为两类,一种是在非 Web 环境下使用,另一种是在 Web 环境下使用,包含了 java Servlet相关的信息。Subject的整个类图如下所示:
classDiagram
class Subject
<<interface>> Subject
class DelegatingSubject
Subject <|-- DelegatingSubject
class WebDelegatingSubject
DelegatingSubject <|-- WebDelegatingSubject
class WebSubject
<<interface>> WebSubject
Subject <|-- WebSubject
class RequestPairSource
<<interface>> RequestPairSource
RequestPairSource <|-- WebSubject
class WebDelegatingSubject
WebSubject <|-- WebDelegatingSubject
Subject最为最顶层的接口,定义了用户基本信息的接口、登录相关和权限相关的接口。
DelegatingSubject实现了Subject接口,在非 Web 环境下使用。
WebDelegatingSubject则是在 Web 环境下使用,需要依赖于Servlet。
Subject 实例化
工厂类 SubjectFactory
SubjectFactory接口时负责创建并且初始化Subject
|
|
它有两个子类,DefaultSubjectFactory使用在非 Web 环境下,会创建DelegatingSubject实例。DefaultWebSubjectFactory则对应在 Web 环境下,会创建WebDelegatingSubject实例。
初始化参数 SubjectContext
SubjectContext用于初始化Subject的,不同的子类对应着不同类型的Subject。比如下面的DefaultSubjectContext用作非 Web 环境下的DelegatingSubject初始化,而DefaultWebSubjectContext用于 Web 环境下的WebDelegatingSubject初始化。
classDiagram
class SubjectContext
<<interface>> SubjectContext
class Map
<<interface>> Map
Map <|-- SubjectContext
class WebSubjectContext
<<interface>> WebSubjectContext
SubjectContext <|-- WebSubjectContext
class RequestPairSource
<<interface>> RequestPairSource
RequestPairSource <|-- WebSubjectContext
class DefaultSubjectContext
SubjectContext <|-- DefaultSubjectContext
class DefaultWebSubjectContext
DefaultSubjectContext <|-- DefaultWebSubjectContext
WebSubjectContext <|-- DefaultWebSubjectContext
SubjectContext提供了SecurityManager、Session、身份凭证AuthenticationToken、身份信息AuthenticationInfo、客户端 ip 等参数。
DefaultSubjectContext实现了SubjectContext接口,它相当于JavaBean,是上述这些信息的集合类。
DefaultSubjectContext只是在DefaultSubjectContext基础之上,添加了ServletRequest和ServletResponse的操作。
Subject 持久化
SubjectDAO接口定义了Subject的持久化
|
|
目前只有一个实现类DefaultSubjectDAO,它的原理也比较简单,使用了 session 存储信息。它只是存储了用户的身份信息和是否已经成功认证。
| session 属性名 | 类型 | 含义 |
|---|---|---|
DefaultSubjectContext.AUTHENTICATED_SESSION_KEY |
PrincipalCollection |
身份列表(一个用户可能有多个身份) |
DefaultSubjectContext.AUTHENTICATED_SESSION_KEY |
Boolean | 是否通过身份认证 |
login 原理
现在我们来看看从Subject.login方法开始,看看整个 login 的过程。Subject的login方法只有DelegatingSubject子类实现了,它只是将请求转发给DefaultSecurityManager处理。
|
|
再继续看看Subject的创建过程
|
|
上面调用了两个方法doCreateSubject和save方法,最后来看看它们的原理
|
|
整个 login 流程如下图所示:
sequenceDiagram
participant Subject
participant DefaultSecurityManager
participant Authenticator
participant SubjectFactory
participant SubjectDAO
Subject->>+DefaultSecurityManager: login
DefaultSecurityManager->>+Authenticator: authenticate
Authenticator-->>-DefaultSecurityManager: AuthenticationInfo
DefaultSecurityManager->>+SubjectFactory: createSubject
SubjectFactory-->>-DefaultSecurityManager: Subject
DefaultSecurityManager->>+SubjectDAO: save
SubjectDAO-->>-DefaultSecurityManager:
DefaultSecurityManager-->>-Subject: .
logout 原理
在执行Subject.logout方法完成登出操作后,shrio 会将Subject的信息都设置为空,并且会删除关联的 session。