前言
在 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权限。
|
|