springboot shiro ehcache redis 简单使用

引入相关pom

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>      
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>

        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring-boot-web-starter</artifactId>
            <version>1.4.1</version>
        </dependency>

        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-ehcache</artifactId>
            <version>1.4.1</version>
        </dependency>

配置properties

shiro.loginUrl=/login
shiro.unauthorizedUrl=/403


spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.password=123456
spring.redis.timeout=2000

编写ShiroConfig 配置类

    @Bean
    public Realm realm(){
        UserRealm userRealm = new UserRealm();
        userRealm.setCredentialsMatcher(hashedCredentialsMatcher());
        return userRealm;
    }

    @Bean
    @DependsOn({"lifecycleBeanPostProcessor"})
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator(){
        DefaultAdvisorAutoProxyCreator autoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        /**
         * 处理@RequiresRole等shiro注解失效问题
         */
        //autoProxyCreator.setUsePrefix(true);
        autoProxyCreator.setProxyTargetClass(true);
        return autoProxyCreator;
    }

    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(){
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        return authorizationAttributeSourceAdvisor;
    }

    @Bean
    public ShiroFilterChainDefinition shiroFilterChainDefinition(){
        DefaultShiroFilterChainDefinition chain = new DefaultShiroFilterChainDefinition();
        Map<String,String> pathDefinitions = new LinkedHashMap<>();
        pathDefinitions.put("/loginDo","anon");
        pathDefinitions.put("/**","user");
        //authc user anon
        chain.addPathDefinitions(pathDefinitions);
        return chain;
    }


    /**
     * 密码验证
     * @return
     */
    @Bean
    public HashedCredentialsMatcher hashedCredentialsMatcher(){
        RetryLimitHashedCredentialsMatcher credentialsMatcher = new RetryLimitHashedCredentialsMatcher();
        credentialsMatcher.setHashAlgorithmName("MD5");
        credentialsMatcher.setHashIterations(3);
        credentialsMatcher.setStoredCredentialsHexEncoded(true);
        return credentialsMatcher;
    }

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

    @Bean
    public RedisCacheSessionDAO redisCacheSessionDAO(){
        RedisCacheSessionDAO redisCacheSessionDAO = new RedisCacheSessionDAO();
        return redisCacheSessionDAO;
    }


    @Bean
    public SessionManager sessionManager(){
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        sessionManager.setGlobalSessionTimeout(1000 * 60 * 30);
        sessionManager.setSessionIdCookieEnabled(true);
        sessionManager.setSessionIdCookie(sessionIdCookie());
        //sessionManager.setSessionDAO(new EnterpriseCacheSessionDAO());
        sessionManager.setSessionDAO(redisCacheSessionDAO());
        sessionManager.setDeleteInvalidSessions(true);//删除过期session
        sessionManager.setSessionValidationSchedulerEnabled(true);//定期检查session
        return sessionManager;
    }

    @Bean(name = "ehCacheManager")
    public EhCacheManager ehCacheManager(){
        EhCacheManager ehCacheManager = new EhCacheManager();
        return ehCacheManager;
    }

    @Bean(name = "sessionIdCookie")
    public SimpleCookie sessionIdCookie(){
        SimpleCookie cookie = new SimpleCookie("sid");
        cookie.setHttpOnly(true);
        cookie.setMaxAge(-1);//关闭浏览器就过期了 这里也可以设置下过期时间,尽量不重新生成新的sessionId
        return cookie;
    }

    @Bean(name = "rememberMeCookie")
    public SimpleCookie rememberMeCookie(){
        SimpleCookie cookie = new SimpleCookie("rememberMe");
        cookie.setHttpOnly(true);
        cookie.setPath("/notify");
        cookie.setMaxAge(2592000);//30天有效期
        return cookie;
    }

    @Bean(name = "rememberMeManager")
    public CookieRememberMeManager cookieRememberMeManager(){
        CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
        cookieRememberMeManager.setCipherKey(Base64.decode("A7UzJgh1+EWj5oBFi+mSgw=="));
        cookieRememberMeManager.setCookie(rememberMeCookie());
        return cookieRememberMeManager;
    }

    @Bean
    public FormAuthenticationFilter formAuthenticationFilter(){
        FormAuthenticationFilter filter = new FormAuthenticationFilter();
        filter.setUsernameParam("username");
        filter.setPasswordParam("password");
        filter.setRememberMeParam("rememberMe");
        filter.setLoginUrl("/login");
        return filter;
    }

编写RedisCacheSessionDAO

public class RedisCacheSessionDAO extends EnterpriseCacheSessionDAO {

    private static final Logger log = LoggerFactory.getLogger(RedisCacheSessionDAO.class);

    // Session超时时间,单位为秒
    private long expireTime = 3600;

    @Autowired
    private RedisTemplate redisTemplate;

    public RedisCacheSessionDAO() {
        super();
    }

    @Override
    protected Serializable doCreate(Session session) {
        Serializable sessionId = generateSessionId(session);
        assignSessionId(session,sessionId);
        redisTemplate.opsForValue().set(sessionId, session, expireTime, TimeUnit.SECONDS);
        return sessionId;
    }

    @Override
    protected Session doReadSession(Serializable sessionId) {
        if(sessionId == null){
            return null;
        }
        //这里一定要在redis拿到session返回,不然在记住账号(remeberMe=true)的情况下一直生成新的session,不记住账号的情况下登录不上session倒是没少生成    单机下这里返回空是没啥问题的
        return (Session) redisTemplate.opsForValue().get(sessionId);
    }

    @Override
    protected void doUpdate(Session session) {
        super.doUpdate(session);
        if(session == null){
            return;
        }
        session.setTimeout(expireTime * 1000);
        redisTemplate.opsForValue().set(session.getId(), session, expireTime, TimeUnit.SECONDS);
    }

    @Override
    protected void doDelete(Session session) {
        super.doDelete(session);
        if(session == null){
            return;
        }
        redisTemplate.opsForValue().getOperations().delete(session.getId());
    }

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

 cipherKey   字符串生成策略  Base64.decode的字符串参数

KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(128,new SecureRandom("spring-boot-0.0.1".getBytes()));
SecretKey secretKey =keyGenerator.generateKey();
SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getEncoded(),"AES");
//cipherKey
System.out.println(new String(Base64.encode(secretKeySpec.getEncoded())));