Realm:域,Shiro 从 Realm 获取安全数据(如用户、角色、权限),就是说 SecurityManager 要验证用户身份,那么它需要从 Realm 获取相应的用户进行比较以确定用户身份是否合法;也需要从 Realm 得到用户相应的角色/权限进行验证用户是否能进行操作;可以把 Realm 看成 DataSource , 即 安 全 数 据 源 。(摘自《跟我学Shiro》)
Shiro 中 Realm 的继承结构如下:

Realm 接口
Realm
接口是Shiro中所有Realm的顶级接口。在接口中声明了三个方法:
-
String getName();
返回当前领域域的名称;在一个应用程序中,所有的领域对象必须拥有不同的名称;也就是说每个领域对象的名称在同一个应用程序中是唯一的。 -
boolean supports(AuthenticationToken token);
返回当前领域是否支持参数中的token。只有当前Realm支持这个类型的token时,Shiro才会使用这个类型的token调用AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException;
方法进行身份认证。 -
AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException;
返回与参数中token对应用户身份认证信息。
CachingRealm 抽象类
CachingRealm
抽象类是Shiro中唯一一个直接实现Realm
接口的类。同时它还实现了Nameable, CacheManagerAware, LogoutAware
三个接口。CachingRealm
中实现的功能如下:
-
声明了
private String name;
属性,实现了Nameable
接口中的String setName();
方法;并在实现了保证同一程序中所有领域(Realm)都有不同名称的算法逻辑。 -
声明了
private CacheManager cacheManager;
(缓存管理器),实现了CacheManagerAware
接口中的void setCacheManager(CacheManager cacheManager);
方法;缓存管理器可用于管理已认证的主体(Subject)和角色、权限等信息;没有实现缓存管理功能,需要在其子类中进行实现。 -
实现了
LogoutAware
接口中的public void onLogout(PrincipalCollection principals);
方法,实现了当onLogout(退出时)清空对应主体(Subject)缓存的逻辑。 -
声明了
private boolean cachingEnabled;
属性,说明当前领域(Realm)是否支持缓存,并在默认构造方法中设置为了true
。
AuthenticatingRealm 抽象类
AuthenticatingRealm
抽象类是Shiro中唯一一个直接继承自CachingRealm
的类。它还实现了Initializable
接口。AuthenticatingRealm
中实现的功能如下:
-
声明了
private CredentialsMatcher credentialsMatcher;
对象,用于验证主体(Subject)身份的合法性。并在getAuthenticationInfo
方法中调用了CredentialsMatcher 对象的证书(credentials)匹配算法,对token
对象和AuthenticationInfo
对象中的credentials
信息进行比较,实现了主体(Subject)身份认证的算法逻辑。 -
实现了对
AuthenticationInfo
的缓存管理功能,并声明了private Cache<Object, AuthenticationInfo> authenticationCache;
用于缓存AuthenticationInfo
对象,避免短时间内多次从持久化设备中重复读取同一AuthenticationInfo
造成的计算资源浪费,并提高系统反应速度。 -
声明了
protected abstract AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException;
用于从缓存获取AuthenticationInfo
(主体的认证信息)失败时,尝试从持久化设备中读取AuthenticationInfo
。 -
实现了
Initializable
接口中的void init() throws ShiroException;
方法。并实现了初始时获取可用缓存对象(private Cache<Object, AuthorizationInfo> authorizationCache;
)的方法。在init
方法中除获取缓存对象还调用了protected void onInit()
方法,给子类留下了对初始化方法的扩展接口。
AuthorizingRealm 抽象类
AuthorizingRealm
抽象类是Shiro中唯一一个直接继承自AuthenticatingRealm
的类;除些这外它还实现了Authorizer, Initializable, PermissionResolverAware, RolePermissionResolverAware
四个接口。它的功能已经非常完善了,平常我们要实现自己的Realm时一般都是从这个类扩展得到。它所实现的功能如下:
-
实现了授权信息(角色、权限)的缓存、验证等功能。在此类之前的那些类都是针对主体身份认证的,没有涉及授权信息(角色和权限)。
-
对授权信息(角色、权限)实现了缓存功能。声明了
protected abstract AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals);
方法留给子类实现,用于在从缓存读取AuthorizationInfo
(授权信息)失败时,从持久化设备中读取AuthorizationInfo
。 -
实现了
Authorizer
接口中对授权信息(角色、权限)进行验证的方法如下图所示:
对角色和权限进行验证方法
Authorizer、PermissionResolver 及 RolePermissionResolver
Authorizer 的职责是进行授权(访问控制),是 Shiro API 中授权核心的入口点,其提供了相应的角色/权限判断接口。SecurityManager 继承了 Authorizer 接口,且提供了 odularRealmAuthorizer 用于多 Realm 时的授权匹配。PermissionResolver 用于解析权限字符串到 Permission 实例,而 RolePermissionResolver 用于根据角色解析相应的权限集合。
小结
综合以上记录,可知AuthorizingRealm
的已经是一个功能完善的领域(Realm)类了,所以平时我需要实现自己的领域(Realm)类时,通常也是对AuthorizingRealm
进行扩展。
扩展AuthorizingRealm
时,我们只需要实现两个方法就可以了:
-
protected abstract AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals);
从持久化设备中获取当前已授权主体(Subject)的授权信息(角色和权限)。这个方法是在AuthorizingRealm
类中声明的。 -
protected abstract AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException;
从持久化设备中获取主体(Subject)的身份认证信息。这个方法是在AuthenticatingRealm
类中声明的。
在Shiro中,对领域的扩展接口基本就是这样;除了从持久化设备中获取主体的身份认证信息和授权信息(角色、权限)外,其他的所有工作Shiro已经帮我们全做了。
有关 SimpleAccountRealm
,PropertiesRealm
,IniRealm
,JdbcRealm
,JndiLdapRealm
,AbstractLdapRealm
和ActiveDirectoryRealm
类的介绍暂时先放一放;这些类都是针对不同的持久化设备对AuthorizingRealm
类进行的扩展,无外乎是针对不同持久化设备的特性对doGetAuthorizationInfo
和 doGetAuthenticationInfo
方法进行实现而已。等以后有时间了,再另立文章,对它的使用方式进行说明。
启发
从对Realm
的学习中可以了解到以下信息:
-
调用
doGetAuthenticationInfo
方法获取主体(Subject)的身份认证信息时,需要传入一个AuthenticationToken
对象作为参数。请参阅 Shiro 中的 AuthenticationToken。 -
主体(Subject)的身份认证信息是由
AuthenticationInfo
对象表示的。请参阅 Shiro 中的 AuthenticationInfo。 -
主体(Subject)的授权信息(角色、权限)是由
AuthorizationInfo
对象表示的。请参阅 Shiro 中的 AuthorizationInfo。 -
主体的身份认证工作是由
CredentialsMatcher
对象中的证书(credentials)匹配算法完成的。请参阅Shiro 中的 CredentialsMatcher 与 PasswordService。 -
所有对授权信息的验证工作都由
Authorizer
对象完成。后面会有专门介绍Authorizer
的文章。
网友评论