shiro的源码学习(四)-- 深入理解realm

IniRealm的类结构如下图:

下面分析每个类:

(1)Ream:

域的顶点,其代码如下:securityManager会使验证器来调用,验证器通过Realm返回用户信息,确定用户是否登录成功:

1 public interface Realm {
2      String getName();//返回Realm的名字,唯一
3      boolean supports(AuthenticationToken token);//校验token
4      AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException;//返回用户信息
5 }

 (2) CachingRealm:

缓存域,支持用户信息的缓存:可以注入缓存器,支持Realm名字的修改,支持用户的登出:

 1 public abstract class CachingRealm implements Realm, Nameable, CacheManagerAware, LogoutAware {
 2     private String name;
 3     private boolean cachingEnabled;//支持缓存,默认为true
 4     private CacheManager cacheManager; //注入缓存器
 5     public CachingRealm() {
 6         this.cachingEnabled = true;
 7         this.name = getClass().getName() + "_" + INSTANCE_COUNT.getAndIncrement();
 8     }
 9     ...........
10     public void setCacheManager(CacheManager cacheManager) {
11         this.cacheManager = cacheManager;
12         afterCacheManagerSet();
13     }
14     public void onLogout(PrincipalCollection principals) {
15         clearCache(principals);
16     }
17     
18     ........
19 }

 (3)AuthenticatingRealm:

验证器的域,可以注入缓存器,主要是实现CachingRealm扩展的子接口,并支持初始化,doGetAuthenticationInfo(token),由子类实现,

public abstract class AuthenticatingRealm extends CachingRealm implements Initializable {
    private CredentialsMatcher credentialsMatcher;//密码匹配器
    private Cache<Object, AuthenticationInfo> authenticationCache;//用户信息的缓存,相当一个Map集合,用户名={AuthenticationInfo,.....}
    public AuthenticatingRealm() {
       this(null, new SimpleCredentialsMatcher());
     }
    public AuthenticatingRealm(CacheManager cacheManager, CredentialsMatcher matcher) {
    authenticationTokenClass = UsernamePasswordToken.class;
    //retain backwards compatibility for Shiro 1.1 and earlier.  Setting to true by default will probably cause
    //unexpected results for existing applications:
    this.authenticationCachingEnabled = false;//是否验证器的缓存
    int instanceNumber = INSTANCE_COUNT.getAndIncrement();
    this.authenticationCacheName = getClass().getName() + DEFAULT_AUTHORIZATION_CACHE_SUFFIX;
    if (instanceNumber > 0) {
    this.authenticationCacheName = this.authenticationCacheName + "." + instanceNumber;
       }
    if (cacheManager != null) {
      setCacheManager(cacheManager);//设置缓存器
        }
    if (matcher != null) {
         setCredentialsMatcher(matcher);
        }
      }
//实现Realm的获取验证信息
public final AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { AuthenticationInfo info = getCachedAuthenticationInfo(token);//从缓存中获取 if (info == null) { //otherwise not cached, perform the lookup: info = doGetAuthenticationInfo(token);//子类实现,或者自定义的realm里面自己实现 log.debug("Looked up AuthenticationInfo [{}] from doGetAuthenticationInfo", info); if (token != null && info != null) { cacheAuthenticationInfoIfPossible(token, info);//压入到缓存 } } else { log.debug("Using cached authentication info [{}] to perform credentials matching.", info); } if (info != null) { assertCredentialsMatch(token, info); } else { log.debug("No AuthenticationInfo found for submitted AuthenticationToken [{}]. Returning null.", token); } return info; } protected abstract AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException; public boolean supports(AuthenticationToken token) { return token != null && getAuthenticationTokenClass().isAssignableFrom(token.getClass()); } ........ public final void init() { //trigger obtaining the authorization cache if possible getAvailableAuthenticationCache(); onInit(); } }

 (4)AuthorizingRealm:

权限认证器,实现AuthenticatingRealm,Authorizer(用来做权限检查)、PermissionResolverAware(支持自定义的权限解析)、RolePermissionResolverAware(支持自定义的角色权限解析)

public abstract class AuthorizingRealm extends AuthenticatingRealm
    implements Authorizer, Initializable, PermissionResolverAware, RolePermissionResolverAware {
    private boolean authorizationCachingEnabled;//
    private Cache<Object, AuthorizationInfo> authorizationCache;
    private String authorizationCacheName;
    private PermissionResolver permissionResolver;
private RolePermissionResolver permissionRoleResolver;

     public AuthorizingRealm() {
        this(null, null);

     }

     public AuthorizingRealm(CacheManager cacheManager, CredentialsMatcher matcher) {

        super();

        if (cacheManager != null) setCacheManager(cacheManager);
        if (matcher != null) setCredentialsMatcher(matcher);

        this.authorizationCachingEnabled = true;//默认为true
        this.permissionResolver = new WildcardPermissionResolver();//创建权限解析器

        int instanceNumber = INSTANCE_COUNT.getAndIncrement();
        this.authorizationCacheName = getClass().getName() + DEFAULT_AUTHORIZATION_CACHE_SUFFIX;
        if (instanceNumber > 0) {
            this.authorizationCacheName = this.authorizationCacheName + "." + instanceNumber;
         } 
     }

}
//获取权限信息
 protected AuthorizationInfo getAuthorizationInfo(PrincipalCollection principals) {
........
Cache<Object, AuthorizationInfo> cache = getAvailableAuthorizationCache();//先从缓存中获取
  info = doGetAuthorizationInfo(principals);//如果缓存没有,则获取原数据

     if (info == null) {
     // Call template method if the info was not found in a cache
     info = doGetAuthorizationInfo(principals);//
     // If the info is not null and the cache has been created, then cache the authorization info.
     if (info != null && cache != null) {
     if (log.isTraceEnabled()) {
         log.trace("Caching authorization info for principals: [" + principals + "].");
      }
      Object key = getAuthorizationCacheKey(principals);
      cache.put(key, info);
    }
    }

     return info;

} 
//权限判断的例子

   public boolean[] isPermitted(PrincipalCollection subjectIdentifier, String... permissions) {
   List<Permission> perms = new ArrayList<Permission>(permissions.length);
   for (String permString : permissions) {
   perms.add(getPermissionResolver().resolvePermission(permString));
    }
   return isPermitted(subjectIdentifier, perms);
}

    //权限之间的判断

   private boolean isPermitted(Permission permission, AuthorizationInfo info) {
   Collection<Permission> perms = getPermissions(info);
   if (perms != null && !perms.isEmpty()) {
    for (Permission perm : perms) {
   if (perm.implies(permission)) {
    return true;
    }
  }
  }
   return false;
}

 ........

(5)、SimpleAccountRealm:

是对AuthorizingRealm的一个身份验证,主要实现doGetAuthenticationInfo、doGetAuthorizationInfo新口

public class SimpleAccountRealm extends AuthorizingRealm {
    protected final Map<String, SimpleAccount> users; //username-to-SimpleAccount
    protected final Map<String, SimpleRole> roles; //roleName-to-SimpleRole
    protected final ReadWriteLock USERS_LOCK;
    protected final ReadWriteLock ROLES_LOCK;

      public SimpleAccountRealm() {
      this.users = new LinkedHashMap<String, SimpleAccount>();
      this.roles = new LinkedHashMap<String, SimpleRole>();
      USERS_LOCK = new ReentrantReadWriteLock();
      ROLES_LOCK = new ReentrantReadWriteLock();
      //SimpleAccountRealms are memory-only realms - no need for an additional cache mechanism since we're
      //already as memory-efficient as we can be:
      setCachingEnabled(false);
     }

     //获取用户信息

     protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        UsernamePasswordToken upToken = (UsernamePasswordToken) token;
        SimpleAccount account = getUser(upToken.getUsername());

        if (account != null) {

        if (account.isLocked()) {
           throw new LockedAccountException("Account [" + account + "] is locked.");
         }
         if (account.isCredentialsExpired()) {
        String msg = "The credentials for account [" + account + "] are expired";
        throw new ExpiredCredentialsException(msg);
      }

      }

     return account;
}

     //获取权限器信息

     protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
     String username = getUsername(principals);
     USERS_LOCK.readLock().lock();
     try {
     return this.users.get(username);
    } finally {
      USERS_LOCK.readLock().unlock();
     }
    }

    //增加用户信息

    protected void add(SimpleAccount account) {
    String username = getUsername(account);
    USERS_LOCK.writeLock().lock();
    try {
    this.users.put(username, account);
    } finally {
    USERS_LOCK.writeLock().unlock();
     }
    }

}

 (6)TextConfigurationRealm:

主要继承自SimpleAccountRealm,用来配置SimpleAccountRealm的Map<String, SimpleAccount> users,和 Map<String, SimpleRole> roles

//增加roles    
protected void processRoleDefinitions(Map<String, String> roleDefs) {
        if (roleDefs == null || roleDefs.isEmpty()) {
            return;
        }
        for (String rolename : roleDefs.keySet()) {
            String value = roleDefs.get(rolename);

            SimpleRole role = getRole(rolename);
            if (role == null) {
                role = new SimpleRole(rolename);
                add(role);
            }

            Set<Permission> permissions = PermissionUtils.resolveDelimitedPermissions(value, getPermissionResolver());
            role.setPermissions(permissions);
        }
    }
//增加users
    protected void processUserDefinitions(Map<String, String> userDefs) {
        if (userDefs == null || userDefs.isEmpty()) {
            return;
        }
        for (String username : userDefs.keySet()) {

            String value = userDefs.get(username);

            String[] passwordAndRolesArray = StringUtils.split(value);

            String password = passwordAndRolesArray[0];

            SimpleAccount account = getUser(username);
            if (account == null) {
                account = new SimpleAccount(username, password, getName());
                add(account);
            }
            account.setCredentials(password);

            if (passwordAndRolesArray.length > 1) {
                for (int i = 1; i < passwordAndRolesArray.length; i++) {
                    String rolename = passwordAndRolesArray[i];
                    account.addRole(rolename);

                    SimpleRole role = getRole(rolename);
                    if (role != null) {
                        account.addObjectPermissions(role.getPermissions());
                    }
                }
            } else {
                account.setRoles(null);
            }
        }
    }

(7)IniRealm,

通过配置ini来定义user,和role:如:

    private void processDefinitions(Ini ini) {
        if (CollectionUtils.isEmpty(ini)) {
            log.warn("{} defined, but the ini instance is null or empty.", getClass().getSimpleName());
            return;
        }

        Ini.Section rolesSection = ini.getSection(ROLES_SECTION_NAME);//定义全局的role(role包含perm)
        if (!CollectionUtils.isEmpty(rolesSection)) {
            log.debug("Discovered the [{}] section.  Processing...", ROLES_SECTION_NAME);
            processRoleDefinitions(rolesSection);
        }

        Ini.Section usersSection = ini.getSection(USERS_SECTION_NAME);
        if (!CollectionUtils.isEmpty(usersSection)) {
            log.debug("Discovered the [{}] section.  Processing...", USERS_SECTION_NAME);
            processUserDefinitions(usersSection);//配置用户的acount,user,perm
        } else {
            log.info("{} defined, but there is no [{}] section defined.  This realm will not be populated with any " +
                    "users and it is assumed that they will be populated programatically.  Users must be defined " +
                    "for this Realm instance to be useful.", getClass().getSimpleName(), USERS_SECTION_NAME);
        }
    }

总结:

 

 

不解之处有:

SimplePrincipalCollection的 Map<String, Set> realmPrincipals的定义,为什么用Set集合保存Principals

 

转载于:https://www.cnblogs.com/pingqlin341/p/7218884.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值