前言
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。