spring boot 集成shiro,redis,EhCache缓存的主要配置

简介:redis用户缓存用户的session,EhCache用于缓存用户的权限。

问题:即使有EhCache缓存了用户的权限,但是每次访问需要权限的方法时,依然会调用授权方法进行授权。

ShiroConfig.java



import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import com.nongqitong.web.redis.RedisSessionDao;
import com.nongqitong.web.shiro.ShiroFormAuthenticationFilter;
import com.nongqitong.web.shiro.realm.LoginRealm;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.session.mgt.ExecutorServiceSessionValidationScheduler;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.filter.authc.LogoutFilter;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.config.MethodInvokingFactoryBean;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.DelegatingFilterProxy;
import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import java.util.HashMap;
import java.util.Map;

@Configuration
public class ShiroConfig {
    @Bean
    public ShiroDialect shiroDialect() {
        return new ShiroDialect();
    }

    @Bean
    public FilterRegistrationBean filterRegistrationBean() {
        FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
        DelegatingFilterProxy delegatingFilterProxy = new DelegatingFilterProxy("shiroFilterFactoryBean");
        delegatingFilterProxy.setTargetFilterLifecycle(true);
        filterRegistration.setEnabled(true);
        filterRegistration.setFilter(delegatingFilterProxy); //  该值缺省为false,表示生命周期由SpringApplicationContext管理,设置为true则表示由ServletContainer管理  filterRegistration.addInitParameter("targetFilterLifecycle", "true");
        filterRegistration.addUrlPatterns("/*");
        filterRegistration.setDispatcherTypes(DispatcherType.REQUEST);
        return filterRegistration;
    }

    @Bean(name = "shiroFilterFactoryBean")
    public ShiroFilterFactoryBean shiroFilterFactoryBean(
            @Qualifier("securityManager") DefaultWebSecurityManager securityManager) {
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
        bean.setSecurityManager(securityManager);
        bean.setLoginUrl("/");
        Map<String, Filter> filters = new HashMap<>();
        LogoutFilter logoutFilter = new LogoutFilter();
        logoutFilter.setRedirectUrl("/");
        ShiroFormAuthenticationFilter shiroFormAuthenticationFilter = new ShiroFormAuthenticationFilter();
        filters.put("logoutFilter", logoutFilter);
        filters.put("authc", shiroFormAuthenticationFilter);
        bean.setFilters(filters);
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        filterChainDefinitionMap.put("/", "anon");
        filterChainDefinitionMap.put("/google", "anon");
        filterChainDefinitionMap.put("/libs/**", "anon");
//        filterChainDefinitionMap.put("/images/**", "anon");
//        filterChainDefinitionMap.put("/jquery/**", "anon");
//        filterChainDefinitionMap.put("/test/**", "anon");
        filterChainDefinitionMap.put("/user/login", "anon");
        filterChainDefinitionMap.put("/logout", "logout");
        filterChainDefinitionMap.put("/**", "authc");
        bean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return bean;
    }

    @Bean(name = "securityManager")
    public DefaultWebSecurityManager securityManager(@Qualifier("authRealm") LoginRealm authRealm,
                                                     @Qualifier("cacheManager") EhCacheManager cacheManager,
                                                     @Qualifier("sessionManager") ShiroSessionManager sessionManager) {
        DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
        manager.setRealm(authRealm);
        manager.setCacheManager(cacheManager);
        manager.setSessionManager(sessionManager);
        return manager;
    }

    @Bean(name = "authRealm")
    public LoginRealm loginRealm() {
        LoginRealm realm = new LoginRealm();
        realm.setCachingEnabled(true);
        return realm;
    }

    @Bean(name = "cacheManager")
    public EhCacheManager cacheManager() {
        EhCacheManager manager = new EhCacheManager();
        manager.setCacheManagerConfigFile("classpath:ehcache.xml");
        return manager;
    }

    @Bean(name = "sessionManager")
    public ShiroSessionManager sessionManager(@Qualifier("sessionDAO") RedisSessionDao sessionDAO, @Qualifier("sessionIdCookie") SimpleCookie sessionIdCookie) {
        ShiroSessionManager manager = new ShiroSessionManager();
        manager.setGlobalSessionTimeout(1800000);
        manager.setDeleteInvalidSessions(true);
        manager.setSessionValidationSchedulerEnabled(true);
//        manager.setSessionValidationScheduler(sessionValidationScheduler);
        manager.setSessionDAO(sessionDAO);
        manager.setSessionIdCookieEnabled(true);
        manager.setSessionIdCookie(sessionIdCookie);
        manager.setSessionIdUrlRewritingEnabled(false);
        return manager;
    }

    @Bean(name = "sessionValidationScheduler")
    public ExecutorServiceSessionValidationScheduler sessionValidationScheduler(
            @Qualifier("sessionManager") ShiroSessionManager sessionManager) {
        ExecutorServiceSessionValidationScheduler scheduler = new ExecutorServiceSessionValidationScheduler();
        scheduler.setInterval(1800000);
        scheduler.setSessionManager(sessionManager);
        return scheduler;
    }

//    @Bean(name = "sessionDAO")
//    public EnterpriseCacheSessionDAO sessionDAO() {
//        EnterpriseCacheSessionDAO sessionDAO = new EnterpriseCacheSessionDAO();
//        sessionDAO.setSessionIdGenerator(new JavaUuidSessionIdGenerator());
//        return sessionDAO;
//    }
    @Bean(name = "sessionDAO")
    public RedisSessionDao getRedisSessionDao() {
        return new RedisSessionDao();
    }

    @Bean(name = "sessionIdCookie")
    public SimpleCookie sessionIdCookie() {
        SimpleCookie cookie = new SimpleCookie("ryzh.session.id");
        cookie.setHttpOnly(true);
        cookie.setMaxAge(-1);
        return cookie;
    }

    @Bean
    public MethodInvokingFactoryBean methodInvokingFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager) {
        MethodInvokingFactoryBean methodInvokingFactoryBean = new MethodInvokingFactoryBean();
        methodInvokingFactoryBean.setStaticMethod("org.apache.shiro.SecurityUtils.setSecurityManager");
        methodInvokingFactoryBean.setArguments(securityManager);
        return methodInvokingFactoryBean;
    }

//    @Bean("lifecycleBeanPostProcessor")
//    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
//        return new LifecycleBeanPostProcessor();
//    }

    @Bean
//    @DependsOn("lifecycleBeanPostProcessor")
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator shiroAutoProxyCreator =
                new DefaultAdvisorAutoProxyCreator();
        shiroAutoProxyCreator.setProxyTargetClass(true);
        return shiroAutoProxyCreator;
    }



    /**
     *  开启shiro aop注解支持.
     *  使用代理方式;所以需要开启代码支持;否则@RequiresRoles等注解无法生效
     * @param securityManager
     * @return
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Qualifier("securityManager") DefaultWebSecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }


}

ehcache.xml

<?xml version="1.0" encoding="UTF-8"?>
<ehcache name="shirocache">

    <diskStore path="java.io.tmpdir"/>

    <!-- 登录记录缓存 锁定10分钟 -->
    <cache name="passwordRetryCache" eternal="false"
           timeToIdleSeconds="3600" timeToLiveSeconds="0" overflowToDisk="false"
           statistics="true">
    </cache>

    <cache name="authorizationCache" eternal="true"
           timeToIdleSeconds="3600" timeToLiveSeconds="0" overflowToDisk="false"
           statistics="true">
    </cache>

    <cache name="authenticationCache" eternal="true"
           timeToIdleSeconds="3600" timeToLiveSeconds="0" overflowToDisk="false"
           statistics="true">
    </cache>

    <cache name="shiro-activeSessionCache" eternal="false"
           timeToIdleSeconds="3600" timeToLiveSeconds="0" overflowToDisk="false"
           statistics="true">
    </cache>

    <cache name="shiro-kickout-session" eternal="false"
           timeToIdleSeconds="3600" timeToLiveSeconds="0" overflowToDisk="false"
           statistics="true">
    </cache>

    <defaultCache
            maxElementsInMemory="10000"
            eternal="false"
            timeToIdleSeconds="120"

            overflowToDisk="false"
            diskPersistent="false"
            diskExpiryThreadIntervalSeconds="120"
    />
    <!--maxElementsInMemory="10000"-->
    <!--external 设置为true后就不会失效,未测试logout,但切换账号后再切换回来,就会需要重新授权-->
    <!--eternal="false"-->
    <!--缓存空闲时间,只有空闲到一定时长则失效,下次需要重新授权-->
    <!--timeToIdleSeconds="120"-->
    <!--缓存Live时间,超时立刻失效-->
    <!--timeToLiveSeconds="120"-->
    <!--overflowToDisk="false"-->
    <!--diskPersistent="false"-->
    <!--diskExpiryThreadIntervalSeconds="120"-->

</ehcache>

RedisSessionDao.java



import org.apache.shiro.session.Session;
import org.apache.shiro.session.UnknownSessionException;
import org.apache.shiro.session.mgt.eis.AbstractSessionDAO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.io.Serializable;
import java.util.Collection;
import java.util.concurrent.TimeUnit;

@Service
public class RedisSessionDao extends AbstractSessionDAO {
    // Session超时时间,单位为毫秒
    private long expireTime = 1800000;

    @Autowired
    private RedisTemplate redisTemplate;// Redis操作类,对这个使用不熟悉的,可以参考前面的博客

    public RedisSessionDao() {
        super();
    }

    public RedisSessionDao(long expireTime, RedisTemplate redisTemplate) {
        super();
        this.expireTime = expireTime;
        this.redisTemplate = redisTemplate;
    }

    @Override // 更新session
    public void update(Session session) throws UnknownSessionException {
        System.out.println("===============update================");
        if (session == null || session.getId() == null) {
            return;
        }
        session.setTimeout(expireTime);
        redisTemplate.opsForValue().set(session.getId(), session, expireTime, TimeUnit.MILLISECONDS);
    }

    @Override // 删除session
    public void delete(Session session) {
        System.out.println("===============delete================");
        if (null == session) {
            return;
        }
        redisTemplate.opsForValue().getOperations().delete(session.getId());
    }

    @Override
// 获取活跃的session,可以用来统计在线人数,如果要实现这个功能,可以在将session加入redis时指定一个session前缀,统计的时候则使用keys("session-prefix*")的方式来模糊查找redis中所有的session集合
    public Collection<Session> getActiveSessions() {
        System.out.println("==============getActiveSessions=================");
        return redisTemplate.keys("*");
    }

    @Override// 加入session
    protected Serializable doCreate(Session session) {
        System.out.println("===============doCreate================");
        Serializable sessionId = this.generateSessionId(session);
        this.assignSessionId(session, sessionId);
        redisTemplate.opsForValue().set(session.getId(), session, expireTime, TimeUnit.MILLISECONDS);
        return sessionId;
    }

    @Override// 读取session
    protected Session doReadSession(Serializable sessionId) {
        System.out.println("==============doReadSession================= "+sessionId);
        if (sessionId == null) {
            return null;
        }
        return (Session) redisTemplate.opsForValue().get(sessionId);
    }

    public long getExpireTime() {
        return expireTime;
    }

    public void setExpireTime(long expireTime) {
        this.expireTime = expireTime;
    }

    public RedisTemplate getRedisTemplate() {
        return redisTemplate;
    }

    public void setRedisTemplate(RedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;

    }
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值