spring boot shiro redis续

本篇文章是基于前几篇spring boot shiro redis的基础上,如果未看前几篇建议先看前几篇

1:springboot redis整合

2:springboot shiro整合

3:springboot shiro redis整合

4:spring boot shiro redis整合遇到的问题

spring boot shiro 使用redis对session进行管理请看 第3篇文章

shiro的认证,授权信息 也可以交给redis管理
本篇文章会和之前的使用redis管理session的那篇文章有些区别,对session的管理进行了重新实现
shiro的认证,授权信息 有redis管理的思想是:
shiro的认证,授权信息本身支持存放到缓存中,只需把之前shiro默认的ehcache缓存更换成redis缓存即可。

shiro 配置文件如下:重点的会使用红色标注:

package com.zyc.springboot.config;

import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.servlet.Filter;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.codec.Base64;
import org.apache.shiro.session.SessionListener;
import org.apache.shiro.session.mgt.ExecutorServiceSessionValidationScheduler;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.filter.DelegatingFilterProxy;

import com.zyc.springboot.shiro.MyFormAuthenticationFilter;
import com.zyc.springboot.shiro.MyRealm;
import com.zyc.springboot.shiro.MyShiroSessionListener;
import com.zyc.springboot.shiro.RedisUtil;
import com.zyc.springboot.shiro.SessionDao;
import com.zyc.springboot.shiro.ShiroRedisCacheManager;

@Configuration
public class ShiroConfig {
	
	/*@Bean(name = "shiroEhcacheManager")
	public EhCacheManager getEhCacheManager() {
		EhCacheManager em = new EhCacheManager();
		em.setCacheManagerConfigFile("classpath:ehcache-shiro.xml");
		return em;
	}*/
	
	@Bean(name="shiroRedisCacheManager")
	public ShiroRedisCacheManager shiroRedisCacheManager(RedisTemplate redisTemplate){
		ShiroRedisCacheManager shiroRedisCacheManager=new ShiroRedisCacheManager();
		shiroRedisCacheManager.setRedisTemplate(redisTemplate);
		return shiroRedisCacheManager;
	}
	
	@Bean(name = "lifecycleBeanPostProcessor")
	public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
		LifecycleBeanPostProcessor lifecycleBeanPostProcessor = new LifecycleBeanPostProcessor();
		return lifecycleBeanPostProcessor;
	}
	
	@Bean(name = "sessionValidationScheduler")
	public ExecutorServiceSessionValidationScheduler getExecutorServiceSessionValidationScheduler(DefaultWebSessionManager defaultWebSessionManager) {
		ExecutorServiceSessionValidationScheduler scheduler = new ExecutorServiceSessionValidationScheduler();
		scheduler.setInterval(50*1000);
		scheduler.setSessionManager(defaultWebSessionManager);
		return scheduler;
	}
	
	@Bean
	public HashedCredentialsMatcher hashedCredentialsMatcher() {
		HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
		hashedCredentialsMatcher.setHashAlgorithmName("md5");// 散列算法:这里使用MD5算法;
		hashedCredentialsMatcher.setHashIterations(1);// 散列的次数,比如散列两次,相当于md5(md5(""));
		hashedCredentialsMatcher.setStoredCredentialsHexEncoded(true);
		return hashedCredentialsMatcher;
	}
	
	@Bean(name = "defaultWebSecurityManager")
	public DefaultWebSecurityManager defaultWebSecurityManager(MyRealm myRealm,DefaultWebSessionManager defaultWebSessionManager,ShiroRedisCacheManager shiroRedisCacheManager) {
		DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
		defaultWebSecurityManager.setRealm(myRealm);
		//defaultWebSecurityManager.setCacheManager(getEhCacheManager());
		defaultWebSecurityManager.setCacheManager(shiroRedisCacheManager);
		defaultWebSecurityManager.setSessionManager(defaultWebSessionManager);
		defaultWebSecurityManager.setRememberMeManager(rememberMeManager());
		return defaultWebSecurityManager;
	}
	
	@Bean(name = "rememberMeCookie")
	public SimpleCookie rememberMeCookie() {
		// 这个参数是cookie的名称,对应前端的checkbox的name = rememberMe
		SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
		// 
		simpleCookie.setMaxAge(60*60*24*30);
		return simpleCookie;
	}
	
	/**
	 * cookie管理对象;
	 * 
	 * @return
	 */
	@Bean(name = "rememberMeManager")
	public CookieRememberMeManager rememberMeManager() {
		CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
		cookieRememberMeManager.setCookie(rememberMeCookie());
		 byte[] cipherKey = Base64.decode("wGiHplamyXlVB11UXWol8g==");
		cookieRememberMeManager.setCipherKey(cipherKey);
		return cookieRememberMeManager;
	}
	

	@Bean
	@DependsOn(value = "lifecycleBeanPostProcessor")
	public MyRealm myRealm(ShiroRedisCacheManager shiroRedisCacheManager) {
		MyRealm myRealm = new MyRealm();
		//启用缓存
		myRealm.setCachingEnabled(true);
		//启用授权缓存
		myRealm.setAuthorizationCachingEnabled(true);
		myRealm.setAuthorizationCacheName("shiro-AutorizationCache");
		//启用认证信息缓存
		myRealm.setAuthenticationCachingEnabled(true);
		myRealm.setAuthenticationCacheName("shiro-AuthenticationCache");
		myRealm.setCacheManager(shiroRedisCacheManager);
		myRealm.setCredentialsMatcher(hashedCredentialsMatcher());
		return myRealm;
	}

	@Bean
	@DependsOn("lifecycleBeanPostProcessor")
	public DefaultAdvisorAutoProxyCreator getAutoProxyCreator(){
		DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator();
		creator.setProxyTargetClass(true);
		return creator;
	}
	
	@Bean
	public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor(DefaultWebSecurityManager defaultWebSecurityManager) {
		AuthorizationAttributeSourceAdvisor aasa = new AuthorizationAttributeSourceAdvisor();
		aasa.setSecurityManager(defaultWebSecurityManager);
		return aasa;
	}
	

	@Bean(name = "sessionManager")
	public DefaultWebSessionManager defaultWebSessionManager(SessionDao sessionDao) {
		DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
		sessionManager.setGlobalSessionTimeout(1000*60*60*24*60);
//		//url中是否显示session Id
		sessionManager.setSessionIdUrlRewritingEnabled(false);
//		// 删除失效的session
		sessionManager.setDeleteInvalidSessions(true);
		sessionManager.setSessionValidationSchedulerEnabled(true);
		sessionManager.setSessionValidationInterval(18000000);
		sessionManager.setSessionValidationScheduler(getExecutorServiceSessionValidationScheduler(sessionManager));
		//sessionManager.setSessionValidationScheduler(quartzSessionValidationScheduler2(sessionManager));
		//设置SessionIdCookie 导致认证不成功,不从新设置新的cookie,从sessionManager获取sessionIdCookie
		//sessionManager.setSessionIdCookie(simpleIdCookie());
		sessionManager.getSessionIdCookie().setName("session-z-id");
		sessionManager.getSessionIdCookie().setPath("/");
		sessionManager.getSessionIdCookie().setMaxAge(60*60*24*7);
		
		sessionManager.setSessionDAO(sessionDao);
		Collection c=new ArrayList<>();
		c.add(new MyShiroSessionListener());
		sessionManager.setSessionListeners(c);
		
		return sessionManager;
	}
	
//	@Bean
//	public QuartzSessionValidationScheduler2 quartzSessionValidationScheduler2(DefaultWebSessionManager sessionManager){
//		QuartzSessionValidationScheduler2 quartzSessionValidationScheduler2=new QuartzSessionValidationScheduler2();
//		quartzSessionValidationScheduler2.setSessionManager(sessionManager);
//		quartzSessionValidationScheduler2.setSessionValidationInterval(1000*5);
//		return quartzSessionValidationScheduler2;
//	}
	 @Bean
	 public SessionDao sessionDao(RedisUtil redisUtil,ShiroRedisCacheManager shiroRedisCacheManager) {
	 SessionDao sessionDao = new SessionDao();
	 //设置缓存器的名称
	 sessionDao.setActiveSessionsCacheName("shiro-activeSessionCache1");
	 //注入缓存管理器默认的是ehcache缓存
	 sessionDao.setCacheManager(shiroRedisCacheManager);
	 //注入缓存管理器2(实现session由redis控制有多种方法,上一步是一种,下面这样写也行)
	 sessionDao.setRedisUtil(redisUtil);
	 return sessionDao;
	 }
	
	 @Bean
	 public RedisUtil redisUtil(RedisTemplate redisTemplate) {
	 RedisUtil redisUtil = new RedisUtil();
	 redisUtil.setRedisTemplate(redisTemplate);
	 return redisUtil;
	 }

	

	@Bean(name = "filterRegistrationBean1")
	public FilterRegistrationBean filterRegistrationBean() {
		FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
		filterRegistrationBean.setFilter(new DelegatingFilterProxy(
				"shiroFilter"));
		filterRegistrationBean
				.addInitParameter("targetFilterLifecycle", "true");
		filterRegistrationBean.setEnabled(true);
		filterRegistrationBean.addUrlPatterns("/");
//		filterRegistrationBean.setDispatcherTypes(DispatcherType.REQUEST,
//				DispatcherType.FORWARD, DispatcherType.INCLUDE,
//				DispatcherType.ERROR);
		return filterRegistrationBean;
	}

	@Bean(name = "shiroFilter")
	public ShiroFilterFactoryBean shiroFilterFactoryBean(
			@Qualifier("defaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager) {
		// SecurityUtils.setSecurityManager(defaultWebSecurityManager);
		ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
		shiroFilterFactoryBean.setLoginUrl("/login");
		shiroFilterFactoryBean.setSuccessUrl("/getIndex");
		shiroFilterFactoryBean.setUnauthorizedUrl("/login");
		shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
		Map filterMap1 = shiroFilterFactoryBean.getFilters();
		filterMap1.put("authc", new MyFormAuthenticationFilter());
		shiroFilterFactoryBean.setFilters(filterMap1);
		Map filterMap = new LinkedHashMap();
		filterMap.put("/static/**", "anon");
		filterMap.put("/api/**", "anon");
		filterMap.put("/logout", "anon");
		filterMap.put("/login", "authc");
		filterMap.put("/**", "authc");
		shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
		return shiroFilterFactoryBean;
	}

}
@Bean(name="shiroRedisCacheManager")
	public ShiroRedisCacheManager shiroRedisCacheManager(RedisTemplate redisTemplate){
		ShiroRedisCacheManager shiroRedisCacheManager=new ShiroRedisCacheManager();
		shiroRedisCacheManager.setRedisTemplate(redisTemplate);
		return shiroRedisCacheManager;
	}
	
	@Bean(name = "lifecycleBeanPostProcessor")
	public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
		LifecycleBeanPostProcessor lifecycleBeanPostProcessor = new LifecycleBeanPostProcessor();
		return lifecycleBeanPostProcessor;
	}
	
	@Bean(name = "sessionValidationScheduler")
	public ExecutorServiceSessionValidationScheduler getExecutorServiceSessionValidationScheduler(DefaultWebSessionManager defaultWebSessionManager) {
		ExecutorServiceSessionValidationScheduler scheduler = new ExecutorServiceSessionValidationScheduler();
		scheduler.setInterval(50*1000);
		scheduler.setSessionManager(defaultWebSessionManager);
		return scheduler;
	}
	
	@Bean
	public HashedCredentialsMatcher hashedCredentialsMatcher() {
		HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
		hashedCredentialsMatcher.setHashAlgorithmName("md5");// 散列算法:这里使用MD5算法;
		hashedCredentialsMatcher.setHashIterations(1);// 散列的次数,比如散列两次,相当于md5(md5(""));
		hashedCredentialsMatcher.setStoredCredentialsHexEncoded(true);
		return hashedCredentialsMatcher;
	}
	
	@Bean(name = "defaultWebSecurityManager")
	public DefaultWebSecurityManager defaultWebSecurityManager(MyRealm myRealm,DefaultWebSessionManager defaultWebSessionManager,ShiroRedisCacheManager shiroRedisCacheManager) {
		DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
		defaultWebSecurityManager.setRealm(myRealm);
		//defaultWebSecurityManager.setCacheManager(getEhCacheManager());
		defaultWebSecurityManager.setCacheManager(shiroRedisCacheManager);
		defaultWebSecurityManager.setSessionManager(defaultWebSessionManager);
		defaultWebSecurityManager.setRememberMeManager(rememberMeManager());
		return defaultWebSecurityManager;
	}
	
	@Bean(name = "rememberMeCookie")
	public SimpleCookie rememberMeCookie() {
		// 这个参数是cookie的名称,对应前端的checkbox的name = rememberMe
		SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
		// 
		simpleCookie.setMaxAge(60*60*24*30);
		return simpleCookie;
	}
	
	/**
	 * cookie管理对象;
	 * 
	 * @return
	 */
	@Bean(name = "rememberMeManager")
	public CookieRememberMeManager rememberMeManager() {
		CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
		cookieRememberMeManager.setCookie(rememberMeCookie());
		 byte[] cipherKey = Base64.decode("wGiHplamyXlVB11UXWol8g==");
		cookieRememberMeManager.setCipherKey(cipherKey);
		return cookieRememberMeManager;
	}
	

	@Bean
	@DependsOn(value = "lifecycleBeanPostProcessor")
	public MyRealm myRealm(ShiroRedisCacheManager shiroRedisCacheManager) {
		MyRealm myRealm = new MyRealm();
		//启用缓存
		myRealm.setCachingEnabled(true);
		//启用授权缓存
		myRealm.setAuthorizationCachingEnabled(true);
		myRealm.setAuthorizationCacheName("shiro-AutorizationCache");
		//启用认证信息缓存
		myRealm.setAuthenticationCachingEnabled(true);
		myRealm.setAuthenticationCacheName("shiro-AuthenticationCache");
		myRealm.setCacheManager(shiroRedisCacheManager);
		myRealm.setCredentialsMatcher(hashedCredentialsMatcher());
		return myRealm;
	}

	@Bean
	@DependsOn("lifecycleBeanPostProcessor")
	public DefaultAdvisorAutoProxyCreator getAutoProxyCreator(){
		DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator();
		creator.setProxyTargetClass(true);
		return creator;
	}
	
	@Bean
	public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor(DefaultWebSecurityManager defaultWebSecurityManager) {
		AuthorizationAttributeSourceAdvisor aasa = new AuthorizationAttributeSourceAdvisor();
		aasa.setSecurityManager(defaultWebSecurityManager);
		return aasa;
	}
	

	@Bean(name = "sessionManager")
	public DefaultWebSessionManager defaultWebSessionManager(SessionDao sessionDao) {
		DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
		sessionManager.setGlobalSessionTimeout(1000*60*60*24*60);
//		//url中是否显示session Id
		sessionManager.setSessionIdUrlRewritingEnabled(false);
//		// 删除失效的session
		sessionManager.setDeleteInvalidSessions(true);
		sessionManager.setSessionValidationSchedulerEnabled(true);
		sessionManager.setSessionValidationInterval(18000000);
		sessionManager.setSessionValidationScheduler(getExecutorServiceSessionValidationScheduler(sessionManager));
		//sessionManager.setSessionValidationScheduler(quartzSessionValidationScheduler2(sessionManager));
		//设置SessionIdCookie 导致认证不成功,不从新设置新的cookie,从sessionManager获取sessionIdCookie
		//sessionManager.setSessionIdCookie(simpleIdCookie());
		sessionManager.getSessionIdCookie().setName("session-z-id");
		sessionManager.getSessionIdCookie().setPath("/");
		sessionManager.getSessionIdCookie().setMaxAge(60*60*24*7);
		
		sessionManager.setSessionDAO(sessionDao);
		Collection c=new ArrayList<>();
		c.add(new MyShiroSessionListener());
		sessionManager.setSessionListeners(c);
		
		return sessionManager;
	}
	
//	@Bean
//	public QuartzSessionValidationScheduler2 quartzSessionValidationScheduler2(DefaultWebSessionManager sessionManager){
//		QuartzSessionValidationScheduler2 quartzSessionValidationScheduler2=new QuartzSessionValidationScheduler2();
//		quartzSessionValidationScheduler2.setSessionManager(sessionManager);
//		quartzSessionValidationScheduler2.setSessionValidationInterval(1000*5);
//		return quartzSessionValidationScheduler2;
//	}
	 @Bean
	 public SessionDao sessionDao(RedisUtil redisUtil,ShiroRedisCacheManager shiroRedisCacheManager) {
	 SessionDao sessionDao = new SessionDao();
	 //设置缓存器的名称
	 sessionDao.setActiveSessionsCacheName("shiro-activeSessionCache1");
	 //注入缓存管理器默认的是ehcache缓存
	 sessionDao.setCacheManager(shiroRedisCacheManager);
	 //注入缓存管理器2(实现session由redis控制有多种方法,上一步是一种,下面这样写也行)
	 sessionDao.setRedisUtil(redisUtil);
	 return sessionDao;
	 }
	
	 @Bean
	 public RedisUtil redisUtil(RedisTemplate redisTemplate) {
	 RedisUtil redisUtil = new RedisUtil();
	 redisUtil.setRedisTemplate(redisTemplate);
	 return redisUtil;
	 }

	

	@Bean(name = "filterRegistrationBean1")
	public FilterRegistrationBean filterRegistrationBean() {
		FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
		filterRegistrationBean.setFilter(new DelegatingFilterProxy(
				"shiroFilter"));
		filterRegistrationBean
				.addInitParameter("targetFilterLifecycle", "true");
		filterRegistrationBean.setEnabled(true);
		filterRegistrationBean.addUrlPatterns("/");
//		filterRegistrationBean.setDispatcherTypes(DispatcherType.REQUEST,
//				DispatcherType.FORWARD, DispatcherType.INCLUDE,
//				DispatcherType.ERROR);
		return filterRegistrationBean;
	}

	@Bean(name = "shiroFilter")
	public ShiroFilterFactoryBean shiroFilterFactoryBean(
			@Qualifier("defaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager) {
		// SecurityUtils.setSecurityManager(defaultWebSecurityManager);
		ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
		shiroFilterFactoryBean.setLoginUrl("/login");
		shiroFilterFactoryBean.setSuccessUrl("/getIndex");
		shiroFilterFactoryBean.setUnauthorizedUrl("/login");
		shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
		Map filterMap1 = shiroFilterFactoryBean.getFilters();
		filterMap1.put("authc", new MyFormAuthenticationFilter());
		shiroFilterFactoryBean.setFilters(filterMap1);
		Map filterMap = new LinkedHashMap();
		filterMap.put("/static/**", "anon");
		filterMap.put("/api/**", "anon");
		filterMap.put("/logout", "anon");
		filterMap.put("/login", "authc");
		filterMap.put("/**", "authc");
		shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
		return shiroFilterFactoryBean;
	}

}

ShiroRedisCacheManager实现如下:

package com.zyc.springboot.shiro;

import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import org.apache.shiro.cache.CacheManager;
import org.springframework.data.redis.core.RedisTemplate;

/**
 * ClassName: ShiroRedisCacheManager   
 * @author zyc-admin
 * @date 2018年3月1日  
 * @Description: TODO  
 */
public class ShiroRedisCacheManager implements CacheManager {

    private RedisTemplate redisTemplate;
	
	public RedisTemplate getRedisTemplate() {
		return redisTemplate;
	}

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

	@Override
	public  Cache getCache(String arg0) throws CacheException {
		// TODO Auto-generated method stub
		return new ShiroRedisCache<>(arg0,redisTemplate);
	}

}

ShiroRedisCache实现如下:

package com.zyc.springboot.shiro;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import org.springframework.data.redis.core.RedisTemplate;

/**
 * ClassName: ShiroRedisCache
 * 
 * @author zyc-admin
 * @date 2018年3月1日
 * @Description: TODO
 */
@SuppressWarnings("unchecked")
public class ShiroRedisCache implements Cache {

	private String cacheKey;

	
	private RedisTemplate redisTemplate;

	public ShiroRedisCache(String name, RedisTemplate redisTemplate) {
		this.cacheKey="shiro:cache:" + name + ":";
		this.redisTemplate=redisTemplate;
	}

	
	@Override
	public void clear() throws CacheException {
		// TODO Auto-generated method stub
		redisTemplate.delete(keys());
	}

	@Override
	public V get(K arg0) throws CacheException {

		return (V) redisTemplate.opsForValue().get(getCacheKey(arg0));
	}

	@Override
	public Set keys() {

		return redisTemplate.keys(getCacheKey("*"));
	}

	@Override
	public V put(K arg0, V arg1) throws CacheException {
		
		V old = get(arg0);
		redisTemplate.boundValueOps(getCacheKey(arg0)).set(arg1);
		redisTemplate.expire(getCacheKey(arg0), 1, TimeUnit.HOURS);
		return old;
	}

	@Override
	public V remove(K arg0) throws CacheException {
		V old = get(arg0);
		redisTemplate.delete(getCacheKey(arg0));
		return old;
	}

	@Override
	public int size() {
		return keys().size();
	}

	@Override
	public Collection values() {
		Set keys = keys();
		List list = new ArrayList<>();
		for (K s : keys) {
			list.add(get(s));
		}
		return list;
	}

	public String getCacheKey() {
		return cacheKey;
	}

	public K getCacheKey(Object arg0) {
		return (K) (cacheKey + arg0);
	}

	public void setCacheKey(String cacheKey) {
		this.cacheKey = cacheKey;
	}

	public RedisTemplate getRedisTemplate() {
		return redisTemplate;
	}

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

}

对shiro的认证,授权信息 缓存 还需要对MyRealm进行部分重写如下:在退出的时候清除缓存(你也可不清除,看自己项目需求)

package com.zyc.springboot.shiro;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.subject.PrincipalCollection;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.zyc.springboot.entity.User;
import com.zyc.springboot.service.AccountService;
import com.zyc.springboot.util.SpringContext;

public class MyRealm extends AuthorizingRealm {

	@Override
	public CacheManager getCacheManager() {
		// TODO Auto-generated method stub
		return super.getCacheManager();
	}

	/**
	 * 权限认证
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(
			PrincipalCollection principals) {
		System.out.println("授权=====");
		// 获取登录用户的信息,在认证时存储的是ShiroUser 所以得到的就是ShiroUser
		// 在其他地方也可通过SecurityUtils.getSubject().getPrincipals()获取用户信息
		String userName = principals.getPrimaryPrincipal().toString();
		// 权限字符串
		List permissions = new ArrayList<>();
		// 从数据库中获取对应权限字符串并存储permissions
		permissions.add("111");
		// 角色字符串
		List roles = new ArrayList<>();
		// 从数据库中获取对应角色字符串并存储roles

		SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
		simpleAuthorizationInfo.addStringPermissions(permissions);
		simpleAuthorizationInfo.addRoles(roles);// 角色类型

		return simpleAuthorizationInfo;
	}

	/**
	 * 登录验证
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(
			AuthenticationToken arg0) throws AuthenticationException {
		System.out.println("认证=====");
		String userName = ((MyAuthenticationToken) arg0).getUsername();
		char[] password = ((MyAuthenticationToken) arg0).getPassword();
		User user = new User();// 根据用户名密码获取user
		Object obj = new SimpleHash("md5", new String(password), null, 1);
		user.setPassword(obj.toString());
		user.setUserName(userName);
		user = ((AccountService) SpringContext.getBean("accountService"))
				.findByPw(user);
		if (user == null) {
			throw new AuthenticationException("用户名密码错误");
		}

		SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(
				userName, user.getPassword(), this.getName());
		return simpleAuthenticationInfo;
	}

	@Override
	protected void doClearCache(PrincipalCollection principals) {
		// TODO Auto-generated method stub
		super.doClearCache(principals);
		clearCachedAuthenticationInfo(principals);
		clearCachedAuthorizationInfo(principals);
	}

	@Override
	protected void clearCachedAuthenticationInfo(PrincipalCollection principals) {
		// TODO Auto-generated method stub
		super.clearCachedAuthenticationInfo(principals);
		Object key = principals.getPrimaryPrincipal();
		// ShiroUser shiroUser=new ShiroUser();
		// try {
		// BeanUtils.copyProperties(shiroUser, key);
		// } catch (Exception e) {
		// // TODO Auto-generated catch block
		// }
		getAuthenticationCache().remove(key);
	}

	@Override
	protected void clearCachedAuthorizationInfo(PrincipalCollection principals) {
		// TODO Auto-generated method stub
		super.clearCachedAuthorizationInfo(principals);
		Object key = getAuthorizationCacheKey(principals);
		getAuthorizationCache().remove(key);
	}

	protected Object getAuthorizationCacheKey(PrincipalCollection principals) {
		return principals.getPrimaryPrincipal();
	}
}
@Override
	protected void doClearCache(PrincipalCollection principals) {
		// TODO Auto-generated method stub
		super.doClearCache(principals);
		clearCachedAuthenticationInfo(principals);
		clearCachedAuthorizationInfo(principals);
	}

	@Override
	protected void clearCachedAuthenticationInfo(PrincipalCollection principals) {
		// TODO Auto-generated method stub
		super.clearCachedAuthenticationInfo(principals);
		Object key = principals.getPrimaryPrincipal();
		// ShiroUser shiroUser=new ShiroUser();
		// try {
		// BeanUtils.copyProperties(shiroUser, key);
		// } catch (Exception e) {
		// // TODO Auto-generated catch block
		// }
		getAuthenticationCache().remove(key);
	}

	@Override
	protected void clearCachedAuthorizationInfo(PrincipalCollection principals) {
		// TODO Auto-generated method stub
		super.clearCachedAuthorizationInfo(principals);
		Object key = getAuthorizationCacheKey(principals);
		getAuthorizationCache().remove(key);
	}

	protected Object getAuthorizationCacheKey(PrincipalCollection principals) {
		return principals.getPrimaryPrincipal();
	}
}

本篇redis缓存sessio的代码改动了如下:主要是sessiondao本身也支持缓存,之前没发现,现在使用自带的功能加以修正,简单方便

package com.zyc.springboot.shiro;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.io.Serializable;

import org.apache.shiro.session.Session;
import org.apache.shiro.session.mgt.SimpleSession;
import org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;


public class SessionDao extends EnterpriseCacheSessionDAO {
	private String cacheKey="shiro:cache:shiro-activeSessionCache1:";
	private RedisUtil redisUtil;
	public RedisUtil getRedisUtil() {
		return redisUtil;
	}

	public void setRedisUtil(RedisUtil redisUtil) {
		this.redisUtil = redisUtil;
	}

	// 创建session,保存到数据库
    @Override
    protected Serializable doCreate(Session session) {
        @SuppressWarnings("unused")
		Serializable sessionId = super.doCreate(session);
        //redisUtil.set(cacheKey+session.getId().toString(), sessionToByte(session),1*60L);
        getCacheManager().getCache("shiro-activeSessionCache1").put(session.getId().toString(), session);
        return session.getId();
    }

    // 获取session
    @Override
    protected Session doReadSession(Serializable sessionId) {
        // 先从缓存中获取session,如果没有再去数据库中获取
        //Session session = super.doReadSession(sessionId); 
//        if(session == null){
//            byte[] bytes = (byte[]) redisUtil.get(sessionId.toString());
//            if(bytes != null && bytes.length > 0){
//                session = byteToSession(bytes);    
//            }
//        }
    	Session session = getActiveSessionsCache().get(sessionId);
        return session;
    }

    // 更新session的最后一次访问时间
    @Override
    protected void doUpdate(Session session) {
        super.doUpdate(session);
        //redisUtil.set(session.getId().toString(), sessionToByte(session),1*60L);
        getActiveSessionsCache().put(session.getId().toString(), session);
    }

    // 删除session
    @Override
    protected void doDelete(Session session) {
    	System.out.println("doDelete......");
//        super.doDelete(session);
//        redisUtil.remove(session.getId().toString());
    	getActiveSessionsCache().remove(session.getId().toString());
    }

    // 把session对象转化为byte保存到redis中
    public byte[] sessionToByte(Session session){
        ByteArrayOutputStream bo = new ByteArrayOutputStream();
        byte[] bytes = null;
        try {
            ObjectOutput oo = new ObjectOutputStream(bo);
            oo.writeObject(session);
            bytes = bo.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return bytes;
    }
    
    // 把byte还原为session
    public Session byteToSession(byte[] bytes){
        ByteArrayInputStream bi = new ByteArrayInputStream(bytes);
        ObjectInputStream in;
        SimpleSession session = null;
        try {
            in = new ObjectInputStream(bi);
            session = (SimpleSession) in.readObject();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    
        return session;
    }
}  getCacheManager().getCache("shiro-activeSessionCache1").put(session.getId().toString(), session);
        return session.getId();
    }

    // 获取session
    @Override
    protected Session doReadSession(Serializable sessionId) {
        // 先从缓存中获取session,如果没有再去数据库中获取
        //Session session = super.doReadSession(sessionId); 
//        if(session == null){
//            byte[] bytes = (byte[]) redisUtil.get(sessionId.toString());
//            if(bytes != null && bytes.length > 0){
//                session = byteToSession(bytes);    
//            }
//        }
    	Session session = getActiveSessionsCache().get(sessionId);
        return session;
    }

    // 更新session的最后一次访问时间
    @Override
    protected void doUpdate(Session session) {
        super.doUpdate(session);
        //redisUtil.set(session.getId().toString(), sessionToByte(session),1*60L);
        getActiveSessionsCache().put(session.getId().toString(), session);
    }

    // 删除session
    @Override
    protected void doDelete(Session session) {
    	System.out.println("doDelete......");
//        super.doDelete(session);
//        redisUtil.remove(session.getId().toString());
    	getActiveSessionsCache().remove(session.getId().toString());
    }

    // 把session对象转化为byte保存到redis中
    public byte[] sessionToByte(Session session){
        ByteArrayOutputStream bo = new ByteArrayOutputStream();
        byte[] bytes = null;
        try {
            ObjectOutput oo = new ObjectOutputStream(bo);
            oo.writeObject(session);
            bytes = bo.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return bytes;
    }
    
    // 把byte还原为session
    public Session byteToSession(byte[] bytes){
        ByteArrayInputStream bi = new ByteArrayInputStream(bytes);
        ObjectInputStream in;
        SimpleSession session = null;
        try {
            in = new ObjectInputStream(bi);
            session = (SimpleSession) in.readObject();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    
        return session;
    }
}
package com.zyc.zspringboot.shiro;

import org.apache.shiro.session.Session;
import org.apache.shiro.session.SessionListener;

import com.zyc.zspringboot.util.SpringContext;

public class MyShiroSessionListener implements SessionListener {

	@Override
	public void onStart(Session session) {

	}

	@Override
	public void onStop(Session session) {
		// TODO 退出登录时,先调用此方法,然后会继续调用SessionDao中的doDelete方法
		System.out.println("onStop===" + session.getId());
		RedisUtil redisUtil = (RedisUtil) SpringContext.getBean("redisUtil");
		// 清除session
		redisUtil.remove(session.getId().toString());
		// 清除缓存
		redisUtil.remove("shiro:cache:shiro-activeSessionCache1:"
				+ session.getId().toString());
	}

	@Override
	public void onExpiration(Session session) {
		System.out.println("onExpiration===" + session.getId());
		RedisUtil redisUtil = (RedisUtil) SpringContext.getBean("redisUtil");
		// 清除session
		redisUtil.remove(session.getId().toString());
		// 清除缓存
		redisUtil.remove("shiro:cache:shiro-activeSessionCache1:"
				+ session.getId().toString());
	}

}

整合完毕,如果遇到部分问题,可以看之前写的几篇文章中是否已经提到并解决,也可留言提出问题,我及时更新改正

你可能感兴趣的:(spring-boot)