前言
在 shiro 框架的文章中,了解到Realm
是用作获取用户身份信息和权限信息的。shiro 将这块分离出来,使得我们可以自定义,以适应不同的场景。比如用户的信息可以存储数据库中,也在外面添加了一层缓存,我们可以实现自己的Realm
,完成缓存和数据库的读取操作。
Realm 接口
先来看看Realm
接口的定义,它的方法只有三个,涉及到了AuthenticationToken
和AuthenticationInfo
两个概念。
|
|
身份凭证
AuthenticationToken
是认证的凭证,可以简单的看作是账户名和密码。
|
|
下面是AuthenticationToken
相关接口的类图
classDiagram
class AuthenticationToken
<<interface>> AuthenticationToken
class HostAuthenticationToken
<<interface>> HostAuthenticationToken
AuthenticationToken <|-- HostAuthenticationToken
class RememberMeAuthenticationToken
<<interface>> RememberMeAuthenticationToken
AuthenticationToken <|-- RememberMeAuthenticationToken
class UsernamePasswordToken
HostAuthenticationToken <|-- UsernamePasswordToken
RememberMeAuthenticationToken <|-- UsernamePasswordToken
class BearerToken
HostAuthenticationToken <|-- BearerToken
HostAuthenticationToken
添加了客户端的ip接口,RememberMeAuthenticationToken
添加了是否需要记住我的接口。我们接着需要看看子类的实现,UsernamePasswordToken
和BearerToken
。
UsernamePasswordToken
是用于账户名和密码的验证方式,所以它会保存这两个属性,当作Principal
和Credentials
。
|
|
BearerToken
是用于基于 token 的验证方式,所以它的Principal
和Credentials
都是 token。当使用 jwt 验证时,就可以使用BearerToken
。
|
|
身份认证结果
AuthenticationInfo
表示身份认证后的结果,包含了用户的身份信息。需要注意下getPrincipals
返回的是身份集合,因为当存在多个Realm
时,一个账户有可能是有多个身份的。
|
|
AuthenticationInfo
的相关类图如下所示,注意到右上边的AuthorizationInfo
接口,它包含了用户的权限。
classDiagram
class AuthenticationInfo
<<interface>> AuthenticationInfo
class SaltedAuthenticationInfo
<<interface>> SaltedAuthenticationInfo
AuthenticationInfo <|-- SaltedAuthenticationInfo
class MergableAuthenticationInfo
<<interface>> MergableAuthenticationInfo
AuthenticationInfo <|-- MergableAuthenticationInfo
class SimpleAuthenticationInfo
SaltedAuthenticationInfo <|-- SimpleAuthenticationInfo
MergableAuthenticationInfo <|-- SimpleAuthenticationInfo
class AuthorizationInfo
<<interface>> AuthorizationInfo
class Account
<<interface>> Account
AuthenticationInfo <|-- Account
AuthorizationInfo <|-- Account
class SimpleAccount
Account <|-- SimpleAccount
MergableAuthenticationInfo <|-- SimpleAccount
SaltedAuthenticationInfo <|-- SimpleAccount
SaltedAuthenticationInfo
支持加盐操作,MergableAuthenticationInfo
支持合并用户身份信息。
SimpleAuthenticationInfo
也只是简单的实现,保存了对应的属性。
SimpleAccount
实现了AuthenticationInfo
接口,保存了身份信息,也实现了AuthorizationInfo
接口,保存了用户的权限。
Realm 子类
现在可以回过来看看 Realm 的子类,首先来看看它的类图
classDiagram
class Realm
<<interface>> Realm
class CachingRealm
<<abstract>> CachingRealm
Realm <|-- CachingRealm
class AuthenticatingRealm
<<abstract>> AuthenticatingRealm
CachingRealm <|-- AuthenticatingRealm
class AuthorizingRealm
<<abstract>> AuthorizingRealm
class Authorizer
<<interface>> Authorizer
Authorizer <|-- AuthorizingRealm
AuthenticatingRealm <|-- AuthorizingRealm
CachingRealm
提供了缓存管理,在后续子类中会用到。
AuthenticatingRealm
实现了身份认证。
AuthorizingRealm
实现了权限检查。
由于CachingRealm
类比较简单,这里就不做详细介绍了,对于AuthenticatingRealm
和AuthorizingRealm
需要详细介绍。
我们先来仔细看看AuthenticatingRealm
的原理,它负责返回用户的身份信息,并且会将结果缓存。
|
|
继续看AuthorizingRealm
的原理,它实现了Authorizer
接口,负责返回用户的权限,并且也缓存结果。
|
|
系统自带 Realm
shrio 已经实现了多个 Realm 的子类,如下图所示。
classDiagram
class AuthorizingRealm
class SimpleAccountRealm
AuthorizingRealm <|-- SimpleAccountRealm
class TextConfigurationRealm
SimpleAccountRealm <|-- TextConfigurationRealm
class IniRealm
TextConfigurationRealm <|-- IniRealm
class PropertiesRealm
TextConfigurationRealm <|-- PropertiesRealm
class JdbcRealm
AuthorizingRealm <|-- JdbcRealm
class SaltAwareJdbcRealm
JdbcRealm <|-- SaltAwareJdbcRealm
class AbstractLdapRealm
<<abstract>> AbstractLdapRealm
AuthorizingRealm <|-- AbstractLdapRealm
class ActiveDirectoryRealm
AbstractLdapRealm <|-- ActiveDirectoryRealm
这些子类按照使用场景分为三类,左边以SimpleAccountRealm
为父类的,表示用户信息都存储到内存里。TextConfigurationRealm
表示从文件中加载信息到内存,它的子类IniRealm
表示读取ini
格式的配置文件,PropertiesRealm
表示读取properties
格式的配置文件。
中间以JdbcRealm
为父类的,表示用户信息存储在数据库中。它的子类SaltAwareJdbcRealm
在其基础之上,增加了盐,可以看作是一种加密手段。
右边以AbstractLdapRealm
为父类的,表示用户信息存储在ldap
服务中。ActiveDirectoryRealm
表示采用了ActiveDirectory
服务,它是ldap
实现的一种。
自定义 Realm
上面介绍了Realm
的设计思想,这里会介绍我们该如何使用Realm
。我们在自定义Realm
时,只需要继承AuthorizingRealm
,然后实现它的两个方法即可。
|
|
这里写个简单的例子,只允许admin
用户登录,它只有read
权限。
|
|