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

授权与认证类似

原文地址:https://www.cnblogs.com/BINGJJFLY/p/9112665.html

时间: 2024-11-02 19:28:53

Shiro 缓存认证信息和授权信息的相关文章

Shiro缓存(十三)

使用缓存,可以解决每次访问请求都查数据库的问题.第一次授权后存入缓存. 缓存流程 shiro中提供了对认证信息和授权信息的缓存.shiro默认是关闭认证信息缓存的,对于授权信息的缓存shiro默认开启的.主要研究授权信息缓存,因为授权的数据量大. 用户认证通过. 该 用户第一次授权:调用realm查询数据库 该 用户第二次授权:不调用realm查询数据库,直接从缓存中取出授权信息(权限标识符). -------------------------------------使用ehcache缓存框架

Shiro learning - 认证流程

Shiro认证流程 在学习认证流程之前,你应该先了解Shiro的基本使用流程 认证 身份认证: 证明用户是谁.用户需要提供相关的凭证principals(身份标识)和Credentials (凭证,证明你是这个用户,可以理解成密码) Principals: 用户的属性,可以有多个.但是至少有一个属性能唯一用户 Credentials: 证明信息,密码或者证书之类的 认证流程 token传给Subject.login(Token).在调用login方法时候,内部完成了认证和授权 实际上的认证是由S

项目一:第十四天 1.在realm中动态授权 2.Shiro整合ehcache 缓存realm中授权信息 3.动态展示菜单数据 4.Quartz定时任务调度框架—Spring整合javamail发送邮件 5.基于poi实现分区导出

1 Shiro整合ehCache缓存授权信息 当需要进行权限校验时候:四种方式url拦截.注解.页面标签.代码级别,当需要验证权限会调用realm中的授权方法   Shiro框架内部整合好缓存管理器,整合ehcache环境,只需要配置即可.     <dependency> <groupId>net.sf.ehcache</groupId> <artifactId>ehcache-core</artifactId> <version>

使用Shiro实现认证和授权(基于SpringBoot)

Apache Shiro是一个功能强大且易于使用的Java安全框架,它为开发人员提供了一种直观,全面的身份验证,授权,加密和会话管理解决方案.下面是在SpringBoot中使用Shiro进行认证和授权的例子,代码如下: pom.xml 导入SpringBoot和Shiro依赖: <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>s

Spring boot +Spring Security + Thymeleaf 认证失败返回错误信息

spring boot以其众多友谊的特性,如零配置.微服务等,吸引了很多的粉丝.而其与Spring Security安全框架的无缝结合,使其具备的安全的特性.在此基础上使用Thymeleaf模板引擎进行渲染,静动态结合,让页面开发更加简单.直观. 通过表单提交登录的用户名和密码是登录接口比较常见的一种设计.在初学的过程中,我也不例外的采用个这种方式.表单设计见下图. 登录成功,完成正常的主页面跳转,这个不存在问题.存在问题的是,登录失败了该咋办呢?我就在考虑,由于thymeleaf的局部刷新操作

使用第三方登录无法获取授权信息的可能原因。

项目中的第三方登录本来好好的,可以拿到授权信息,但是过了大概半个月,去看的时候发现授权之后怎么都拿不到第三方账号的信息了,纠结了好多天,准备从友盟换ShareSDK,demo都写好了,准备换的时候发现自己的代码设置里有这样一段代码,是iOS9之后官方推荐的设置回调的方法. //iOS9之后官方推荐用此方法 - (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *,i

查看帐号授权信息

查看指定帐号的授权信息 1 select OBJECT_NAME (id), USER_NAME (uid), 2 case action 3 when 193 then 'select' 4 when 195 then 'insert' 5 when 196 then 'delete' 6 when 197 then 'update' 7 when 224 then 'execute' 8 else null end , 9 case protecttype 10 when 205 then

缓存外部系统接口返回信息的方案

概要: 在一个大的系统当中,通常会切分成多个子系统,子系统与子系统之间可以通过微服务.http接口或者mq等来相互通讯.假设有这样一种场景,A系统需要调用B系统的f1 接口,获取数据后再向前端系统输出. 前端系统通常所承受的并发量是非常大的,也就是说A系统的接口需要有很高的qps. 这个时候我们需要缓存B系统接口的输出,以便提高A系统接口的响应速度. 详细内容请看我的csdn博客链接: 缓存外部系统接口返回信息的方案

小程序获取授权信息

1,open-type,不授权使用头像昵称 2,获取用户信息,需要授权------然后login--后台获取 3,获取用户信息,只能通过button ,open-type 4,getsetting获取授权的信息 5,opensetting获取已经授权的设置 6,openauthing:获取非用户信息的授权 7,getuserinfo不弹出了,必须button调用 原文地址:https://www.cnblogs.com/bluestear/p/9865004.html