Spring Shiro基础组件 Realm

相关阅读

简介

定义了访问安全实体,比如:用户、角色、权限的接口,以支持鉴权和授权操作;

核心方法

/**
 * 返回名称
 * 应用程序内唯一
 */
String getName();

/**
 * 是否支持指定AuthenticationToken
 */
boolean supports(AuthenticationToken token);

/**
 * 鉴权
 */
AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException;

实现子类

public interface Realm
    public abstract class CachingRealm implements Realm, Nameable, CacheManagerAware, LogoutAware    // 实现getName()接口,提供缓存算法模板,由子类实现算法细节和选择是否开启缓存功能
        public abstract class AuthenticatingRealm extends CachingRealm implements Initializable  // 实现supports(AuthenticationToken)接口/缓存算法细节/getAuthenticationInfo(AuthenticationToken)算法模板/init()算法模板,提供抽象方法doGetAuthenticationInfo(AuthenticationToken)onInit()方法默认实现,由子类实现算法细节
            public abstract class AuthorizingRealm extends AuthenticatingRealm implements Authorizer, Initializable, PermissionResolverAware, RolePermissionResolverAware    // 实现obInit()算法细节/getAuthorizationInfo(PrincipalCollection)算法模板,提供抽象方法doGetAuthorizationInfo(PrincipalCollection)由子类实现算法细节
                public class SimpleAccountRealm extends AuthorizingRealm           // 实现doGetAuthenticationInfo(AuthenticationToken)/doGetAuthorizationInfo(PrincipalCollection)算法细节

CachingRealm

简介

扩展Realm接口的基础抽象类,提供缓存支持;
同时提供getAvailablePrincipal(PrincipalCollection)方法获取领域特定的主体/身份信息;

核心方法

// 名称,默认className_id(递增的原子Integer)
private String name;
// 开启缓存标识,默认true
private boolean cachingEnabled;
// 缓存管理器
private CacheManager cacheManager;

/**
 * 模板方法
 */
public void setCacheManager(CacheManager cacheManager) {
    this.cacheManager = cacheManager;
    afterCacheManagerSet();
}

/**
 * 模版子方法,由子类实现覆写添加额外的处理逻辑
 */
protected void afterCacheManagerSet() {
}

/**
 * 登出时清除缓存
 */
public void onLogout(PrincipalCollection principals) {
    clearCache(principals);
}

/**
 * 清除缓存
 */
protected void clearCache(PrincipalCollection principals) {
    // 主体集合不为空
    if (!isEmpty(principals)) {
        doClearCache(principals);
        log.trace("Cleared cache entries for account with principals [{}]", principals);
    }
}

/**
 * 清除缓存模板方法
 * 具体动作由子类实现
 */
protected void doClearCache(PrincipalCollection principals) {
}

/**
 * 获取可用principal
 */
protected Object getAvailablePrincipal(PrincipalCollection principals) {
    Object primary = null;
    if (!isEmpty(principals)) {
        // 尝试获取此特定领域的“主要”主体
        Collection thisPrincipals = principals.fromRealm(getName());
        if (!CollectionUtils.isEmpty(thisPrincipals)) {
            primary = thisPrincipals.iterator().next();
        } else {
            // 获取全局的“主要”主体
            //no principals attributed to this particular realm.  Fall back to the 'master' primary:
            primary = principals.getPrimaryPrincipal();
        }
    }

    return primary;
}

AuthenticatingRealm

简介

Realm的顶级抽象实现,仅实现身份验证(登录),授权(访问控制)由子类实现;
默认情况下禁止身份验证缓存,保证和Shiro1.1及更早版本的向后兼容性;
当领域满足以下任一条件才能启动身份验证缓存:

  1. doGetAuthenticationInfo实现返回的AuthenticationInfo实例,其中credentials被加密;
  2. doGetAuthenticationInfo实现返回的AuthenticationInfo实例,其中credentials未加密,但存储AuthenticationInfo实例的缓存区域不会溢出到磁盘,并且不会通过不安全的网络传输缓存条目;
    如果启用身份验证缓存,此抽象类实现会将子类实现返回的AuthenticationInfo实例直接放入缓存中;

核心方法

// 判断给定的credentials是否匹配已存储的值
private Credentialsmatcher credentialsMatcher;
// 身份验证缓存
private Cache<Object, AuthenticationInfo> authenticationCache;
// 身份验证缓存开启标识
private boolean authenticationCachingEnable;
// 身份验证缓存名称
private String authenticationCacheName;
// 此领域支持的身份验证令牌的类型,Realm.supports(AuthenticationToken)默认实现使用其判断给定的身份验证令牌类型是否支持
private Class<? extends AuthenticationToken> authenticationTokenClass;

/**
 * 构造方法
 */
public AuthenticatingRealm(CacheManager cacheManager, CredentialsMatcher matcher) {
    // 默认为UsernamePasswordToken
    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_AUTHENTICATION_CACHE_SUFFIX;
    if (instanceNumber > 0) {
        this.authenticationCacheName = this.authenticationCacheName + "." + instanceNumber;
    }

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

/**
 * 是否开启身份验证缓存
 */
public boolean isAuthenticationCachingEnabled() {
    return this.authenticationCachingEnabled && isCachingEnabled();
}

/**
 * 设置身份验证缓存开启标识
 */
public void setAuthenticationCachingEnabled(boolean authenticationCachingEnabled) {
    this.authenticationCachingEnabled = authenticationCachingEnabled;
    if (authenticationCachingEnabled) {
        // 开启缓存则需要更新父类开启缓存标识
        setCachingEnabled(true);
    }
}

/**
 * 设置身份验证缓存名称
 */
public void setName(String name) {
    super.setName(name);
    String authcCacheName = this.authenticationCacheName;
    if (authcCacheName != null && authcCacheName.startsWith(getClass().getName())) {
        // 如果缓存名称存在且为默认格式,则更新为当前设置的名称
        //get rid of the default heuristically-created cache name.  Create a more meaningful one
        //based on the application-unique Realm name:
        this.authenticationCacheName = name + DEFAULT_AUTHENTICATION_CACHE_SUFFIX;
    }
}

/**
 * Realm.supports的默认实现
 * getAuthenticationTokenClass()默认为UsernamePasswordToken
 * 子类修改默认实现只需要通过setAuthenticationTokenClass修改authenticationTokenClass即可
 */
public boolean supports(AuthenticationToken token) {
    return token != null && getAuthenticationTokenClass().isAssignableFrom(token.getClass());
}

/**
 * 模板方法,初始化
 * 如果cache/cacheManager存在,则先从缓存中查找,否则每次都会由子类实现从底层数据存储中查找
 */
public final void init() {
    //trigger obtaining the authorization cache if possible
    getAvailableAuthenticationCache();
    onInit();
}

/**
 * 获取可用的身份验证缓存
 */
private Cache<Object, AuthenticationInfo> getAvailableAuthenticationCache() {
    Cache<Object, AuthenticationInfo> cache = getAuthenticationCache();
    boolean authcCachingEnabled = isAuthenticationCachingEnabled();
    if (cache == null && authcCachingEnabled) {
        // 如果cache不存在且开启身份验证缓存,则从cacheManager中获取缓存
        cache = getAuthenticationCacheLazy();
    }
    return cache;
}

/**
 * 从可用的缓存管理器中获取身份验证缓存
 */
private Cache<Object, AuthenticationInfo> getAuthenticationCacheLazy() {

    // 校验身份验证缓存是否为空
    if (this.authenticationCache == null) {
        log.trace("No authenticationCache instance set.  Checking for a cacheManager...");

        CacheManager cacheManager = getCacheManager();

        // 如果缓存管理器可用
        if (cacheManager != null) {
            String cacheName = getAuthenticationCacheName();
            log.debug("CacheManager [{}] configured.  Building authentication cache '{}'", cacheManager, cacheName);
            // 根据缓存名称查找缓存
            this.authenticationCache = cacheManager.getCache(cacheName);
        }
    }

    return this.authenticationCache;
}

/**
 * 模板子方法,由子类覆写添加额外的处理逻辑
 */
protected void onInit() {
}

/**
 * 根据token从缓存中查找身份验证信息
 */
private AuthenticationInfo getCachedAuthenticationInfo(AuthenticationToken token) {
    AuthenticationInfo info = null;

    Cache<Object, AuthenticationInfo> cache = getAvailableAuthenticationCache();
    if (cache != null && token != null) {
        log.trace("Attempting to retrieve the AuthenticationInfo from cache.");
        Object key = getAuthenticationCacheKey(token);
        info = cache.get(key);
        if (info == null) {
            log.trace("No AuthorizationInfo found in cache for key [{}]", key);
        } else {
            log.trace("Found cached AuthorizationInfo for key [{}]", key);
        }
    }

    return info;
}

/**
 * 缓存身份验证信息
 */
private void cacheAuthenticationInfoIfPossible(AuthenticationToken token, AuthenticationInfo info) {
    if (!isAuthenticationCachingEnabled(token, info)) {
        log.debug("AuthenticationInfo caching is disabled for info [{}].  Submitted token: [{}].", info, token);
        //return quietly, caching is disabled for this token/info pair:
        return;
    }

    Cache<Object, AuthenticationInfo> cache = getAvailableAuthenticationCache();
    if (cache != null) {
        Object key = getAuthenticationCacheKey(token);
        cache.put(key, info);
        log.trace("Cached AuthenticationInfo for continued authentication.  key=[{}], value=[{}].", key, info);
    }
}

/**
 * 模板方法,获取身份验证信息
 * 先从缓存中获取
 * 缓存获取失败,则由子类实现从底层数据存储中获取
 * 获取到后再次校验token和info是否匹配
 */
public final AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {

    // 先从缓存中查找
    AuthenticationInfo info = getCachedAuthenticationInfo(token);
    if (info == null) {
        // 由子类实现从底层数据存储中查找
        //otherwise not cached, perform the lookup:
        info = doGetAuthenticationInfo(token);
        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) {
        // 校验token和info是否匹配
        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;

/**
 * 校验token是否匹配info
 */
protected void assertCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) throws AuthenticationException {
    CredentialsMatcher cm = getCredentialsMatcher();
    if (cm != null) {
        if (!cm.doCredentialsMatch(token, info)) {
            //not successful - throw an exception to indicate this:
            String msg = "Submitted credentials for token [" + token + "] did not match the expected credentials.";
            throw new IncorrectCredentialsException(msg);
        }
    } else {
        throw new AuthenticationException("A CredentialsMatcher must be configured in order to verify " +
                "credentials during authentication.  If you do not wish for credentials to be examined, you " +
                "can configure an " + AllowAllCredentialsMatcher.class.getName() + " instance.");
    }
}

/**
 * 根据token获取缓存中身份验证信息对应的键
 * 存储缓存时使用的键
 * 默认使用token.getPrincipal(一般是用户名)
 */
protected Object getAuthenticationCacheKey(AuthenticationToken token) {
    return token != null ? token.getPrincipal() : null;
}

/**
 * 根据principalCollection获取缓存中身份验证信息对应的键
 * 清除缓存时使用的健
 * 如果登出时删除账户缓存的身份验证信息,需要保证该方法返回值和getAuthenticationInfoCacheKey(AuthenticationToken)一致
 */
protected Object getAuthenticationCacheKey(PrincipalCollection principals) {
    return getAvailablePrincipal(principals);
}

/**
 * 清除缓存
 */
@Override
protected void doClearCache(PrincipalCollection principals) {
    // 调用父类方法进行清除
    super.doClearCache(principals);
    // 清除缓存的身份验证信息
    clearCachedAuthenticationInfo(principals);
}

/**
 * 清除缓存的身份验证信息
 */
protected void clearCachedAuthenticationInfo(PrincipalCollection principals) {
    if (!isEmpty(principals)) {
        Cache<Object, AuthenticationInfo> cache = getAvailableAuthenticationCache();
        //cache instance will be non-null if caching is enabled:
        if (cache != null) {
            // 根据principals生成缓存的KEY
            Object key = getAuthenticationCacheKey(principals);
            cache.remove(key);
        }
    }
}

AuthorizingRealm

简介

AuthenticatingRealms的基础上增加授权(访问控制)支持;

核心方法

// 授权缓存开启标识
private boolean authorizationCachingEnabled;
// 授权缓存
private Cache<Object, AuthorizationInfo> authorizationCache;
// 授权缓存名称
private String authorizationCacheName;
// 权限解析器
private PermissionResolver permissionResolver;
// 权限角色解析器
private RolePermissionResolver permissionRoleResolver;

/**
 * 构造方法
 */
public AuthorizingRealm(CacheManager cacheManager, CredentialsMatcher matcher) {
    super();
    if (cacheManager != null) setCacheManager(cacheManager);
    if (matcher != null) setCredentialsMatcher(matcher);

    // 默认开启授权缓存
    this.authorizationCachingEnabled = true;
    // 默认权限解析器为WildcardPermissionResolver
    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;
    }
}

/**
 * 设置缓存名称
 */
public void setName(String name) {
    // 设置父类缓存名称
    super.setName(name);
    String authzCacheName = this.authorizationCacheName;
    if (authzCacheName != null && authzCacheName.startsWith(getClass().getName())) {
        //get rid of the default class-name based cache name.  Create a more meaningful one
        //based on the application-unique Realm name:
        this.authorizationCacheName = name + DEFAULT_AUTHORIZATION_CACHE_SUFFIX;
    }
}

/**
 * 授权
 * 算法模板
 */
protected AuthorizationInfo getAuthorizationInfo(PrincipalCollection principals) {

    if (principals == null) {
        return null;
    }

    AuthorizationInfo info = null;

    if (log.isTraceEnabled()) {
        log.trace("Retrieving AuthorizationInfo for principals [" + principals + "]");
    }

    // 先从授权缓存中获取
    Cache<Object, AuthorizationInfo> cache = getAvailableAuthorizationCache();
    if (cache != null) {
        if (log.isTraceEnabled()) {
            log.trace("Attempting to retrieve the AuthorizationInfo from cache.");
        }
        // 获取缓存KEY
        Object key = getAuthorizationCacheKey(principals);
        info = cache.get(key);
        if (log.isTraceEnabled()) {
            if (info == null) {
                log.trace("No AuthorizationInfo found in cache for principals [" + principals + "]");
            } else {
                log.trace("AuthorizationInfo found in cache for principals [" + 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) {
            // 缓存授权信息
            // 思考,如果这时候authorizationCachingEnabled为false,是不是不应该缓存?
            // 建议和AuthenticatingRealm.cacheAuthenticationInfoIfPossible实现一致
            if (log.isTraceEnabled()) {
                log.trace("Caching authorization info for principals: [" + principals + "].");
            }
            Object key = getAuthorizationCacheKey(principals);
            cache.put(key, info);
        }
    }

    return info;
}

/**
 * 根据PrincipalCollection生成缓存KEY
 */
protected Object getAuthorizationCacheKey(PrincipalCollection principals) {
    return principals;
}

/**
 * 授权时处理
 * 算法细节,由子类实现从底层数据存储中查找授权信息
 */
protected abstract AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals);

/**
 * 清除PrincipalCollection关联的缓存
 */
@Override
protected void doClearCache(PrincipalCollection principals) {
    // 调用父类方法清除关联缓存
    super.doClearCache(principals);
    // 清除授权缓存
    clearCachedAuthorizationInfo(principals);
}

/**
 * 清除PrincipalCollection关联的授权缓存
 */
protected void clearCachedAuthorizationInfo(PrincipalCollection principals) {
    if (principals == null) {
        return;
    }

    Cache<Object, AuthorizationInfo> cache = getAvailableAuthorizationCache();
    //cache instance will be non-null if caching is enabled:
    if (cache != null) {
        // 清除授权缓存
        Object key = getAuthorizationCacheKey(principals);
        cache.remove(key);
    }
}

/**
 * 获取授权信息中的权限列表
 */
protected Collection<Permission> getPermissions(AuthorizationInfo info) {
    Set<Permission> permissions = new HashSet<Permission>();

    if (info != null) {
        // 获取类型安全的权限
        Collection<Permission> perms = info.getObjectPermissions();
        if (!CollectionUtils.isEmpty(perms)) {
            permissions.addAll(perms);
        }
        // 获取基于字符串的权限
        perms = resolvePermissions(info.getStringPermissions());
        if (!CollectionUtils.isEmpty(perms)) {
            permissions.addAll(perms);
        }
        // 获取基于角色的权限
        perms = resolveRolePermissions(info.getRoles());
        if (!CollectionUtils.isEmpty(perms)) {
            permissions.addAll(perms);
        }
    }

    if (permissions.isEmpty()) {
        return Collections.emptySet();
    } else {
        return Collections.unmodifiableSet(permissions);
    }
}

/**
 * 解析基于字符串的权限
 */
private Collection<Permission> resolvePermissions(Collection<String> stringPerms) {
    Collection<Permission> perms = Collections.emptySet();
    PermissionResolver resolver = getPermissionResolver();
    if (resolver != null && !CollectionUtils.isEmpty(stringPerms)) {
        perms = new LinkedHashSet<Permission>(stringPerms.size());
        for (String strPermission : stringPerms) {
            if (StringUtils.clean(strPermission) != null) {
                // 解析权限
                Permission permission = resolver.resolvePermission(strPermission);
                perms.add(permission);
            }
        }
    }
    return perms;
}

/**
 * 解析基于角色的权限
 */
private Collection<Permission> resolveRolePermissions(Collection<String> roleNames) {
    Collection<Permission> perms = Collections.emptySet();
    RolePermissionResolver resolver = getRolePermissionResolver();
    if (resolver != null && !CollectionUtils.isEmpty(roleNames)) {
        perms = new LinkedHashSet<Permission>(roleNames.size());
        for (String roleName : roleNames) {
            // 解析权限
            Collection<Permission> resolved = resolver.resolvePermissionsInRole(roleName);
            if (!CollectionUtils.isEmpty(resolved)) {
                perms.addAll(resolved);
            }
        }
    }
    return perms;
}

/**
 * 判断PrincipalCollection关联的授权信息是否包含指定字符串权限
 */
public boolean isPermitted(PrincipalCollection principals, String permission) {
    // 解析基于字符串的权限
    Permission p = getPermissionResolver().resolvePermission(permission);
    return isPermitted(principals, p);
}

/**
 * 判断PrincipalCollection关联的授权信息是否包含指定权限
 */
public boolean isPermitted(PrincipalCollection principals, Permission permission) {
    AuthorizationInfo info = getAuthorizationInfo(principals);
    return isPermitted(permission, info);
}

/**
 * 判断授权信息是否包含指定权限
 */
//visibility changed from private to protected per SHIRO-332
protected 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;
}

/**
 * 批量判断授权信息是否包含指定字符串权限列表
 */
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);
}

public boolean[] isPermitted(PrincipalCollection principals, List<Permission> permissions) {
    AuthorizationInfo info = getAuthorizationInfo(principals);
    return isPermitted(permissions, info);
}

/**
 * 批量判断授权信息是否包含指定权限集合
 */
protected boolean[] isPermitted(List<Permission> permissions, AuthorizationInfo info) {
    boolean[] result;
    if (permissions != null && !permissions.isEmpty()) {
        int size = permissions.size();
        result = new boolean[size];
        int i = 0;
        // 遍历指定权限列表
        for (Permission p : permissions) {
            result[i++] = isPermitted(p, info);
        }
    } else {
        result = new boolean[0];
    }
    return result;
}

/**
 * 判断PrincipalCollection关联的授权信息是否包含指定字符串权限列表
 */
public boolean isPermittedAll(PrincipalCollection subjectIdentifier, String... permissions) {
    if (permissions != null && permissions.length > 0) {
        Collection<Permission> perms = new ArrayList<Permission>(permissions.length);
        for (String permString : permissions) {
            // 解析基于字符串的权限
            perms.add(getPermissionResolver().resolvePermission(permString));
        }
        return isPermittedAll(subjectIdentifier, perms);
    }
    return false;
}

/**
 * 判断PrincipalCollection关联的授权信息是否包含指定权限集合
 */
public boolean isPermittedAll(PrincipalCollection principal, Collection<Permission> permissions) {
    AuthorizationInfo info = getAuthorizationInfo(principal);
    return info != null && isPermittedAll(permissions, info);
}

/**
 * 判断授权信息是否包含指定权限集合
 */
protected boolean isPermittedAll(Collection<Permission> permissions, AuthorizationInfo info) {
    if (permissions != null && !permissions.isEmpty()) {
        for (Permission p : permissions) {
            if (!isPermitted(p, info)) {
                return false;
            }
        }
    }
    return true;
}

/**
 * 校验PrincipalCollection关联的授权信息是否包含指定字符串权限
 */
public void checkPermission(PrincipalCollection subjectIdentifier, String permission) throws AuthorizationException {
    // 解析基于字符串的权限
    Permission p = getPermissionResolver().resolvePermission(permission);
    checkPermission(subjectIdentifier, p);
}

/**
 * 校验PrincipalCollection关联的授权信息是否包含指定权限
 */
public void checkPermission(PrincipalCollection principal, Permission permission) throws AuthorizationException {
    AuthorizationInfo info = getAuthorizationInfo(principal);
    checkPermission(permission, info);
}

/**
 * 校验授权信息是否包含指定权限
 */
protected void checkPermission(Permission permission, AuthorizationInfo info) {
    if (!isPermitted(permission, info)) {
        String msg = "User is not permitted [" + permission + "]";
        throw new UnauthorizedException(msg);
    }
}

/**
 * 校验PrincipalCollection关联的授权信息是否包含指定字符串权限列表
 */
public void checkPermissions(PrincipalCollection subjectIdentifier, String... permissions) throws AuthorizationException {
    if (permissions != null) {
        for (String permString : permissions) {
            checkPermission(subjectIdentifier, permString);
        }
    }
}

/**
 * 校验PrincipalCollection关联的授权信息是否包含指定权限集合
 */
public void checkPermissions(PrincipalCollection principal, Collection<Permission> permissions) throws AuthorizationException {
    // 获取身份验证信息
    AuthorizationInfo info = getAuthorizationInfo(principal);
    checkPermissions(permissions, info);
}

/**
 * 校验授权信息是否包含指定权限集合
 */
protected void checkPermissions(Collection<Permission> permissions, AuthorizationInfo info) {
    if (permissions != null && !permissions.isEmpty()) {
        for (Permission p : permissions) {
            checkPermission(p, info);
        }
    }
}

/**
 * 判断PrincipalCollection关联的授权信息是否包含指定角色
 */
public boolean hasRole(PrincipalCollection principal, String roleIdentifier) {
    AuthorizationInfo info = getAuthorizationInfo(principal);
    return hasRole(roleIdentifier, info);
}

/**
 * 判断授权信息是否包含指定角色
 */
protected boolean hasRole(String roleIdentifier, AuthorizationInfo info) {
    return info != null && info.getRoles() != null && info.getRoles().contains(roleIdentifier);
}

/**
 * 批量判断PrincipalCollection关联的授权信息是否包含指定角色集合
 */
public boolean[] hasRoles(PrincipalCollection principal, List<String> roleIdentifiers) {
    AuthorizationInfo info = getAuthorizationInfo(principal);
    boolean[] result = new boolean[roleIdentifiers != null ? roleIdentifiers.size() : 0];
    if (info != null) {
        result = hasRoles(roleIdentifiers, info);
    }
    return result;
}

/**
 * 批量判断授权信息是否包含指定角色集合
 */
protected boolean[] hasRoles(List<String> roleIdentifiers, AuthorizationInfo info) {
    boolean[] result;
    if (roleIdentifiers != null && !roleIdentifiers.isEmpty()) {
        int size = roleIdentifiers.size();
        result = new boolean[size];
        int i = 0;
        for (String roleName : roleIdentifiers) {
            result[i++] = hasRole(roleName, info);
        }
    } else {
        result = new boolean[0];
    }
    return result;
}

/**
 * 判断PrincipalCollection关联的授权信息是否包含指定角色集合
 */
public boolean hasAllRoles(PrincipalCollection principal, Collection<String> roleIdentifiers) {
    AuthorizationInfo info = getAuthorizationInfo(principal);
    return info != null && hasAllRoles(roleIdentifiers, info);
}

/**
 * 判断授权信息是否包含指定角色集合
 */
private boolean hasAllRoles(Collection<String> roleIdentifiers, AuthorizationInfo info) {
    if (roleIdentifiers != null && !roleIdentifiers.isEmpty()) {
        for (String roleName : roleIdentifiers) {
            if (!hasRole(roleName, info)) {
                return false;
            }
        }
    }
    return true;
}

/**
 * 校验PrincipalCollection关联的授权信息是否包含指定角色
 */
public void checkRole(PrincipalCollection principal, String role) throws AuthorizationException {
    AuthorizationInfo info = getAuthorizationInfo(principal);
    checkRole(role, info);
}

/**
 * 校验授权信息是否包含指定角色
 */
protected void checkRole(String role, AuthorizationInfo info) {
    if (!hasRole(role, info)) {
        String msg = "User does not have role [" + role + "]";
        throw new UnauthorizedException(msg);
    }
}

/**
 * 校验PrincipalCollection关联的授权信息是否包含指定角色集合
 */
public void checkRoles(PrincipalCollection principal, Collection<String> roles) throws AuthorizationException {
    AuthorizationInfo info = getAuthorizationInfo(principal);
    checkRoles(roles, info);
}

/**
 * 校验授权信息是否包含指定角色列表
 */
public void checkRoles(PrincipalCollection principal, String... roles) throws AuthorizationException {
    checkRoles(principal, Arrays.asList(roles));
}

/**
 * 校验授权信息是否包含指定角色集合
 */
protected void checkRoles(Collection<String> roles, AuthorizationInfo info) {
    if (roles != null && !roles.isEmpty()) {
        for (String roleName : roles) {
            checkRole(roleName, info);
        }
    }
}

SimpleAccountRealm

简介

SimpleAccountRealmAuthorizingRealm的简单实现,使用配置的用户账户集合和角色集合来支持身份验证和授权;
每个用户账户指定用户名、密码、角色;角色映射权限,并和用户关联;
用户账户和角色存储在内存的Map中,所以两者总数不能太大;

核心方法

// 存储用户账户
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 SimpleAccount getUser(String username) {
    USERS_LOCK.readLock().lock();
    try {
        return this.users.get(username);
    } finally {
        USERS_LOCK.readLock().unlock();
    }
}

/**
 * 判断指定用户名是否存在
 */
public boolean accountExists(String username) {
    return getUser(username) != null;
}

/**
 * 增加用户
 */
public void addAccount(String username, String password) {
    addAccount(username, password, (String[]) null);
}

/**
 * 增加用户
 */
public void addAccount(String username, String password, String... roles) {
    Set<String> roleNames = CollectionUtils.asSet(roles);
    SimpleAccount account = new SimpleAccount(username, password, getName(), roleNames, null);
    add(account);
}

/**
 * 获取账户的用户名
 */
protected String getUsername(SimpleAccount account) {
    return getUsername(account.getPrincipals());
}

/**
 * 获取账户的用户名
 */
protected String getUsername(PrincipalCollection principals) {
    return getAvailablePrincipal(principals).toString();
}

/**
 * 增加用户
 */
protected void add(SimpleAccount account) {
    // 获取用户名
    String username = getUsername(account);
    USERS_LOCK.writeLock().lock();
    try {
        this.users.put(username, account);
    } finally {
        USERS_LOCK.writeLock().unlock();
    }
}

/**
 * 根据角色名称查找角色
 */
protected SimpleRole getRole(String rolename) {
    ROLES_LOCK.readLock().lock();
    try {
        return roles.get(rolename);
    } finally {
        ROLES_LOCK.readLock().unlock();
    }
}

/**
 * 判断指定角色名是否存在
 */
public boolean roleExists(String name) {
    return getRole(name) != null;
}

/**
 * 增加角色
 */
public void addRole(String name) {
    add(new SimpleRole(name));
}

/**
 * 增加角色
 */
protected void add(SimpleRole role) {
    ROLES_LOCK.writeLock().lock();
    try {
        roles.put(role.getName(), role);
    } finally {
        ROLES_LOCK.writeLock().unlock();
    }
}

/**
 * 字符串切分成Set
 */
protected static Set<String> toSet(String delimited, String delimiter) {
    if (delimited == null || delimited.trim().equals("")) {
        return null;
    }

    Set<String> values = new HashSet<String>();
    String[] rolenamesArray = delimited.split(delimiter);
    for (String s : rolenamesArray) {
        String trimmed = s.trim();
        if (trimmed.length() > 0) {
            values.add(trimmed);
        }
    }

    return values;
}

/**
 * 鉴权时处理
 * 算法细节,根据token从内存MAP中获取鉴权信息
 */
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;
}

/**
 * 授权时处理
 * 算法细节,根据PrincipalCollection从内存MAP中获取授权信息
 */
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
    String username = getUsername(principals);
    USERS_LOCK.readLock().lock();
    try {
        return this.users.get(username);
    } finally {
        USERS_LOCK.readLock().unlock();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值