Shiro 中的 Realm

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

Shiro 中 Realm 的继承结构如下:

Shiro 中的 Realm_第1张图片
Realm 的继承结构 —— 摘自《跟我学Shiro》

Realm 接口

Realm 接口是Shiro中所有Realm的顶级接口。在接口中声明了三个方法:

  1. String getName();返回当前领域域的名称;在一个应用程序中,所有的领域对象必须拥有不同的名称;也就是说每个领域对象的名称在同一个应用程序中是唯一的。

  2. boolean supports(AuthenticationToken token); 返回当前领域是否支持参数中的token。只有当前Realm支持这个类型的token时,Shiro才会使用这个类型的token调用 AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException; 方法进行身份认证。

  3. AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException;返回与参数中token对应用户身份认证信息。

CachingRealm 抽象类

CachingRealm 抽象类是Shiro中唯一一个直接实现Realm接口的类。同时它还实现了Nameable, CacheManagerAware, LogoutAware三个接口。CachingRealm中实现的功能如下:

  1. 声明了private String name;属性,实现了Nameable接口中的String setName();方法;并在实现了保证同一程序中所有领域(Realm)都有不同名称的算法逻辑。

  2. 声明了private CacheManager cacheManager;(缓存管理器),实现了CacheManagerAware接口中的void setCacheManager(CacheManager cacheManager);方法;缓存管理器可用于管理已认证的主体(Subject)和角色、权限等信息;没有实现缓存管理功能,需要在其子类中进行实现。

  3. 实现了LogoutAware接口中的public void onLogout(PrincipalCollection principals);方法,实现了当onLogout(退出时)清空对应主体(Subject)缓存的逻辑。

  4. 声明了private boolean cachingEnabled;属性,说明当前领域(Realm)是否支持缓存,并在默认构造方法中设置为了true

AuthenticatingRealm 抽象类

AuthenticatingRealm 抽象类是Shiro中唯一一个直接继承自CachingRealm的类。它还实现了Initializable接口。AuthenticatingRealm中实现的功能如下:

  1. 声明了private CredentialsMatcher credentialsMatcher;对象,用于验证主体(Subject)身份的合法性。并在getAuthenticationInfo方法中调用了CredentialsMatcher 对象的证书(credentials)匹配算法,对token对象和AuthenticationInfo对象中的credentials信息进行比较,实现了主体(Subject)身份认证的算法逻辑。

  2. 实现了对AuthenticationInfo的缓存管理功能,并声明了private Cache authenticationCache;用于缓存AuthenticationInfo对象,避免短时间内多次从持久化设备中重复读取同一AuthenticationInfo造成的计算资源浪费,并提高系统反应速度。

  3. 声明了protected abstract AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException;用于从缓存获取AuthenticationInfo(主体的认证信息)失败时,尝试从持久化设备中读取AuthenticationInfo

  4. 实现了Initializable接口中的void init() throws ShiroException;方法。并实现了初始时获取可用缓存对象(private Cache authorizationCache;)的方法。在init方法中除获取缓存对象还调用了protected void onInit()方法,给子类留下了对初始化方法的扩展接口。

AuthorizingRealm 抽象类

AuthorizingRealm 抽象类是Shiro中唯一一个直接继承自AuthenticatingRealm的类;除些这外它还实现了Authorizer, Initializable, PermissionResolverAware, RolePermissionResolverAware四个接口。它的功能已经非常完善了,平常我们要实现自己的Realm时一般都是从这个类扩展得到。它所实现的功能如下:

  1. 实现了授权信息(角色、权限)的缓存、验证等功能。在此类之前的那些类都是针对主体身份认证的,没有涉及授权信息(角色和权限)。

  2. 对授权信息(角色、权限)实现了缓存功能。声明了protected abstract AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals);方法留给子类实现,用于在从缓存读取AuthorizationInfo(授权信息)失败时,从持久化设备中读取AuthorizationInfo

  3. 实现了Authorizer接口中对授权信息(角色、权限)进行验证的方法如下图所示:

    Shiro 中的 Realm_第2张图片
    对角色和权限进行验证方法

Authorizer、PermissionResolver 及 RolePermissionResolver

Authorizer 的职责是进行授权(访问控制),是 Shiro API 中授权核心的入口点,其提供了相应的角色/权限判断接口。SecurityManager 继承了 Authorizer 接口,且提供了 odularRealmAuthorizer 用于多 Realm 时的授权匹配。PermissionResolver 用于解析权限字符串到 Permission 实例,而 RolePermissionResolver 用于根据角色解析相应的权限集合。

小结

综合以上记录,可知AuthorizingRealm的已经是一个功能完善的领域(Realm)类了,所以平时我需要实现自己的领域(Realm)类时,通常也是对AuthorizingRealm进行扩展。

扩展AuthorizingRealm时,我们只需要实现两个方法就可以了:

  1. protected abstract AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals);从持久化设备中获取当前已授权主体(Subject)的授权信息(角色和权限)。这个方法是在AuthorizingRealm类中声明的。

  2. protected abstract AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException;从持久化设备中获取主体(Subject)的身份认证信息。这个方法是在AuthenticatingRealm类中声明的。

在Shiro中,对领域的扩展接口基本就是这样;除了从持久化设备中获取主体的身份认证信息和授权信息(角色、权限)外,其他的所有工作Shiro已经帮我们全做了。

有关 SimpleAccountRealm,PropertiesRealm,IniRealm,JdbcRealm,JndiLdapRealm,AbstractLdapRealmActiveDirectoryRealm类的介绍暂时先放一放;这些类都是针对不同的持久化设备对AuthorizingRealm类进行的扩展,无外乎是针对不同持久化设备的特性对doGetAuthorizationInfodoGetAuthenticationInfo 方法进行实现而已。等以后有时间了,再另立文章,对它的使用方式进行说明。

启发

从对Realm的学习中可以了解到以下信息:

  1. 调用doGetAuthenticationInfo方法获取主体(Subject)的身份认证信息时,需要传入一个AuthenticationToken对象作为参数。请参阅 Shiro 中的 AuthenticationToken。

  2. 主体(Subject)的身份认证信息是由 AuthenticationInfo 对象表示的。请参阅 Shiro 中的 AuthenticationInfo。

  3. 主体(Subject)的授权信息(角色、权限)是由 AuthorizationInfo对象表示的。请参阅 Shiro 中的 AuthorizationInfo。

  4. 主体的身份认证工作是由CredentialsMatcher对象中的证书(credentials)匹配算法完成的。请参阅Shiro 中的 CredentialsMatcher 与 PasswordService。

  5. 所有对授权信息的验证工作都由Authorizer对象完成。后面会有专门介绍Authorizer的文章。

你可能感兴趣的:(Shiro 中的 Realm)