zoukankan      html  css  js  c++  java
  • Shiro 缓存认证信息和授权信息

    spring-shiro.xml文件配置

    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">  
        <property name="realm" ref="customAuthorizingRealm"/>  
        <property name="cacheManager" ref="ehCacheManager"/>  
    </bean>
    
    <bean id="ehCacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
        <property name="cacheManagerConfigFile" value="classpath:shiro/ehcache.xml"/>
    <bean/>
    
    <bean id="customAuthorizingRealm" class="com.wjz.demo.CustomAuthorizingRealm">
        <property name="authenticationCachingEnabled" value="true"/>
      <property name="authorizationCachingEnabled" value="true"/>
    </bean>

    缓存原理

    CachingSecurityManager

    注入缓存管理器到安全管理器中,还需要将缓存管理器注入到领域中

    public void setCacheManager(CacheManager cacheManager) {
        this.cacheManager = cacheManager;
        afterCacheManagerSet();
    }

    RealmSecurityManager

    protected void afterCacheManagerSet() {
        super.afterCacheManagerSet();
        applyCacheManagerToRealms();
    }

    将缓存管理器注入到领域中,存入取出缓存内容均有领域具体实现

    protected void applyCacheManagerToRealms() {
    // 获得由配置部分注入的EhCacheManager CacheManager cacheManager
    = getCacheManager(); Collection<Realm> realms = getRealms(); if (cacheManager != null && realms != null && !realms.isEmpty()) { for (Realm realm : realms) { if (realm instanceof CacheManagerAware) {
              // 将EhCacheManage注入到Realm中 ((CacheManagerAware) realm).setCacheManager(cacheManager); } } } }

    DefaultSecurityManager开始认证

    public Subject login(Subject subject, AuthenticationToken token) throws AuthenticationException {
        AuthenticationInfo info;
        try {
            info = authenticate(token);
        } catch (AuthenticationException ae) {
            try {
                onFailedLogin(token, ae, subject);
            } catch (Exception e) {
                if (log.isInfoEnabled()) {
                    log.info("onFailedLogin method threw an " +
                            "exception.  Logging and propagating original AuthenticationException.", e);
                }
            }
            throw ae; //propagate
        }
    
        Subject loggedIn = createSubject(token, info, subject);
    
        onSuccessfulLogin(token, info, loggedIn);
    
        return loggedIn;
    }
    public AuthenticationInfo authenticate(AuthenticationToken token) throws AuthenticationException {
        return this.authenticator.authenticate(token);
    }

    获得我们自定义的Realm领域如CustomAuthorizingRealm

    protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken) throws AuthenticationException {
        assertRealmsConfigured();
        Collection<Realm> realms = getRealms();
        if (realms.size() == 1) {
            return doSingleRealmAuthentication(realms.iterator().next(), authenticationToken);
        } else {
            return doMultiRealmAuthentication(realms, authenticationToken);
        }
    }

    从缓存中找认证信息,如果没有找到则执行CustomAuthorizingRealm中的doGetAuthenticationInfo方法获得AuthenticationInfo

    public final AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        // 试图从缓存中获得AuthenticationInfo,后文详解#1
        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) {
    // 将获得的AuthenticationInfo放入缓存,后文详解#2 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; }

    书接前文#1

    试图从缓存中获得AuthenticationInfo

    private AuthenticationInfo getCachedAuthenticationInfo(AuthenticationToken token) {
        AuthenticationInfo info = null;
        // 获得可用的缓存,后文详解#1-1
        Cache<Object, AuthenticationInfo> cache = getAvailableAuthenticationCache();
        if (cache != null && token != null) {
            log.trace("Attempting to retrieve the AuthenticationInfo from cache.");
    // 以用户名为key Object key
    = getAuthenticationCacheKey(token);
    // 根据key从缓存中拿到AuthenticationInfo,后文详解#1-2 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; }

    书接前文#1-1

    AuthenticatingRealm中有一个Cache<Object, AuthenticationInfo> authenticationCache属性

    private Cache<Object, AuthenticationInfo> getAvailableAuthenticationCache() {
    // 获得authenticationCache Cache
    <Object, AuthenticationInfo> cache = getAuthenticationCache();
    // 默认为false,需要set注入为true,参考配置部分
    boolean authcCachingEnabled = isAuthenticationCachingEnabled(); if (cache == null && authcCachingEnabled) {
    // 使用CacheManager获得Cache对象 cache
    = getAuthenticationCacheLazy(); } return cache; }

    获得EhCacheManager并使用它获得缓存

    private Cache<Object, AuthenticationInfo> getAuthenticationCacheLazy() {
    
        if (this.authenticationCache == null) {
    
            log.trace("No authenticationCache instance set.  Checking for a cacheManager...");
            // 获得EhCacheManager
            CacheManager cacheManager = getCacheManager();
    
            if (cacheManager != null) {
    // 获得缓存的name String cacheName
    = getAuthenticationCacheName(); log.debug("CacheManager [{}] configured. Building authentication cache '{}'", cacheManager, cacheName);
            // 根据缓存的name获得缓存
    this.authenticationCache = cacheManager.getCache(cacheName); } } return this.authenticationCache; }

    EhCacheManager

    public final <K, V> Cache<K, V> getCache(String name) throws CacheException {
    
        if (log.isTraceEnabled()) {
            log.trace("Acquiring EhCache instance named [" + name + "]");
        }
    
        try {
         // ensureCacheManager()获得net.sf.ehcache.CacheManager net.sf.ehcache.Ehcache cache
    = ensureCacheManager().getEhcache(name); if (cache == null) { if (log.isInfoEnabled()) { log.info("Cache with name '{}' does not yet exist. Creating now.", name); }
           // 调用net.sf.ehcache的API
    this.manager.addCache(name); cache = manager.getCache(name); if (log.isInfoEnabled()) { log.info("Added EhCache named [" + name + "]"); } } else { if (log.isInfoEnabled()) { log.info("Using existing EHCache named [" + cache.getName() + "]"); } }
    // 封装net.sf.ehcache为shiro的org.apache.shiro.cache.ehcache.EhCache
    return new EhCache<K, V>(cache); } catch (net.sf.ehcache.CacheException e) { throw new CacheException(e); } }

    net.sf.ehcache.Ehcache

    private net.sf.ehcache.Ehcache cache;
    
    /**
     * Constructs a new EhCache instance with the given cache.
     *
     * @param cache - delegate EhCache instance this Shiro cache instance will wrap.
     */
    public EhCache(net.sf.ehcache.Ehcache cache) {
        if (cache == null) {
            throw new IllegalArgumentException("Cache argument cannot be null.");
        }
        this.cache = cache;
    }

    书接前文#1-2

    shiro的EhCache内部装备一个net.sf.ehcache.Ehcache

    public V get(K key) throws CacheException {
        try {
            if (log.isTraceEnabled()) {
                log.trace("Getting object from cache [" + cache.getName() + "] for key [" + key + "]");
            }
            if (key == null) {
                return null;
            } else {
           // 使用net.sf.ehcache.Ehcache的API获得Element Element element
    = cache.get(key); if (element == null) { if (log.isTraceEnabled()) { log.trace("Element for [" + key + "] is null."); } return null; } else { // 获得缓存中的内容 return (V) element.getObjectValue(); } } } catch (Throwable t) { throw new CacheException(t); } }

    书接前文#2

    将获得的AuthenticationInfo放入缓存

    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); } }

    authenticationCachingEnabled的值默认为false需要set注入为true,cachingEnabled默认为true

    public boolean isAuthenticationCachingEnabled() {
        return this.authenticationCachingEnabled && isCachingEnabled();
    }

    放入缓存

    public V put(K key, V value) throws CacheException {
        if (log.isTraceEnabled()) {
            log.trace("Putting object in cache [" + cache.getName() + "] for key [" + key + "]");
        }
        try {
            V previous = get(key);
            Element element = new Element(key, value);
            cache.put(element);
            return previous;
        } catch (Throwable t) {
            throw new CacheException(t);
        }
    }

    授权与认证类似

  • 相关阅读:
    [日常] Go语言圣经-命令行参数
    [日常] Go语言圣经前言
    [日常] 搭建golang开发环境
    [日常] 研究redis未授权访问漏洞利用过程
    [日常] CentOS安装最新版redis设置远程连接密码
    [日常] Apache Order Deny,Allow的用法
    [日常] 读取队列并循环发信的脚本
    [日常] 20号日常工作总结
    [日常] SinaMail项目和技术能力总结
    [日常] MySQL的预处理技术测试
  • 原文地址:https://www.cnblogs.com/BINGJJFLY/p/9112665.html
Copyright © 2011-2022 走看看