`
phipray
  • 浏览: 66046 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

SpringMVC+Shiro+RedisCluster搭建session统一管理

 
阅读更多

 spring-shiro.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:util="http://www.springframework.org/schema/util"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
		http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd">
	
	<description>Shiro Configuration</description>

    <!-- 加载配置属性文件 -->
	<context:property-placeholder ignore-unresolvable="true" location="classpath*:/csairjee.properties" />
	
	<!-- 安全认证过滤器 -->
	<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
		<property name="securityManager" ref="securityManager" />
<!-- 	<property name="loginUrl" value="${adminPath}/login" />  
		<property name="loginUrl" value="/" />
    	<property name="successUrl" value="${adminPath}" />  
		<property name="successUrl" value="/home/*" />
		<property name="unauthorizedUrl" value="/nopermission.jsp" />
		<property name="filters">
            <map>
                <entry key="authc" value-ref="formAuthenticationFilter"/>
            </map>
        </property> -->
		<property name="filterChainDefinitions">
			<value>
<!--			
				/static/** = anon
				/**/#/home = anon
				/**/uploadPic = anon
				/**/uploadAvatar = anon
				/userfiles/** = anon
				/visitor/** = anon
				/verification/** = anon
				/home/** = authc
				${adminPath}/login = authc
				${adminPath}/logout = logout
				${adminPath}/** = user
-->				
		 	</value>
		</property>
	</bean>
	
	
	
	<!-- 用户授权信息Cache, 采用EhCache -->
	<bean id="shiroCacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
		<property name="cacheManager" ref="cacheManager"/>
	</bean>	
	<!-- EhCache缓存配置 begin-->
	<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
		<property name="configLocation" value="classpath:cache/ehcache-local.xml" />
	</bean>
	<!-- EhCache缓存配置 end-->
	
	
	<!-- Shiro安全接口 -->
	<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">		
		<property name="sessionManager" ref="sessionManager" /> 
		<property name="realm" ref="shiroDbRealm" />
		<property name="cacheManager" ref="shiroCacheManager"></property>
<!-- 	<property name="rememberMeManager.cookie.name" value="rememberMe"/>
    	<property name="rememberMeManager.cookie.maxAge" value="3*60"/>  -->
	</bean>
	
	
	<bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
	    <property name="globalSessionTimeout" value="3600000"/>
	    <property name="sessionDAO" ref="shiroSessionDAO"/>
	    <property name="sessionValidationScheduler" ref="sessionValidationScheduler"/>
	    <property name="sessionValidationSchedulerEnabled" value="true"/>
	    <property name="sessionIdCookie" ref="wapsession"/>
	</bean>	
	
	<!--自定义session存储容器-->
	<bean id="shiroSessionDAO" class="com.csair.csmbp.web.common.shiro.session.impl.ShiroSessionDAO">
        <property name="shiroSessionRepository" ref="redisShiroSessionRepository"></property>       
    </bean>
	
	<!--由redis做session存储容器
	<bean id="redisShiroSessionDAO" class="com.csair.csmbp.web.common.shiro.session.impl.RedisShiroSessionDAO">
        <property name="shiroSessionRepository" ref="redisShiroSessionRepository"></property>
        <property name="expire" value="${mvn.shiro.session.timeout}"></property>
    </bean>
    -->
   
    <!-- custom shiro session listener -->
    <bean id="shiroSessionListener" class="com.csair.csmbp.web.listeners.ShiroSessionListener">
        <property name="shiroSessionRepository" ref="redisShiroSessionRepository"/>
    </bean>
    
    <!-- redis缓存shiro session库 -->
    <bean id="redisShiroSessionRepository" class="com.csair.csmbp.web.common.shiro.session.impl.RedisShiroSessionRepository">
        <property name="jedisClusterHelper" ref="jedisClusterHelper"/>
        <property name="expire" value="${mvn.shiro.session.timeout}"></property>
    </bean>
    
    <!--redisCacheManager要实现org.apache.shiro.cache.CacheManager接口,让shiro使用redis的缓存
    <bean id="shiroCacheManager" class="com.csair.csmbp.web.common.shiro.cache.impl.ShiroCacheManager">
        <property name="customerCacheManager" ref="redisCacheManager"></property>
    </bean> -->
    
    <!-- redis缓存cache 
    <bean id="redisCacheManager" class="com.csair.csmbp.web.common.shiro.cache.impl.RedisCacheManager">
        <property name="jedisClusterHelper" ref="jedisClusterHelper"></property>
    </bean> -->
    
    
	<!--
	指定本系统SESSIONID, 默认为: JSESSIONID
	问题: 与SERVLET容器名冲突, 如JETTY, TOMCAT 等默认JSESSIONID,
	当跳出SHIRO SERVLET时如ERROR-PAGE容器会为JSESSIONID重新分配值导致登录会话丢失!
	-->
	<bean id="wapsession" class="org.apache.shiro.web.servlet.SimpleCookie">
	    <constructor-arg name="name" value="WAPSESSIONID"/>
	</bean>
	<!--
	定时清理僵尸session,Shiro会启用一个后台守护线程定时执行清理操作
	用户直接关闭浏览器造成的孤立会话
	-->
	<bean id="sessionValidationScheduler"
	      class="org.apache.shiro.session.mgt.ExecutorServiceSessionValidationScheduler">
	    <property name="interval" value="3600000"/>
	    <property name="sessionManager" ref="sessionManager"/>
	</bean>
	
	<!-- 用户自定义Realm -->
	<bean  id="shiroDbRealm" class="com.csair.csmbp.web.common.shiro.realm.ShiroDbRealm">
	<!--  <property name="credentialsRealm" ref="customCredentialsRealm"/>  -->
	</bean>	
	
	<!-- 保证实现了Shiro内部lifecycle函数的bean执行 -->
	<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
			
	<!-- AOP式方法级权限检查  启用shiro注解 -->
	<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor">
		<property name="proxyTargetClass" value="true" />
	</bean>
	
	<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
    	<property name="securityManager" ref="securityManager"/>
	</bean>
	
	
	
</beans>

 

在web.xml添加

 <filter>
	    <filter-name>shiroFilter</filter-name>
	    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
	    <init-param>
	      <param-name>targetFilterLifecycle</param-name>
	      <param-value>true</param-value>
	    </init-param>
	 </filter>
	 <filter-mapping>
	    <filter-name>shiroFilter</filter-name>
	    <url-pattern>/*</url-pattern>
	 </filter-mapping>

 

pom.xml中添加

<!-- SECURITY shiro begin -->
		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-core</artifactId>
			<version>${shiro.version}</version>
		</dependency>
		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-spring</artifactId>
			<version>${shiro.version}</version>
		</dependency>
		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-web</artifactId>
			<version>${shiro.version}</version>
		</dependency>
		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-ehcache</artifactId>
			<version>${shiro.version}</version>
		</dependency>
		<!-- SECURITY shiro end -->
-----------------------------------------------------------------------------------
<mvn.redis.clusterserver>10.92.21.17:6379,10.92.21.17:7379,10.92.21.17:8379,10.92.21.18:6380,10.92.21.18:7380,10.92.21.18:8380</mvn.redis.clusterserver>

 config.properties中添加

#Redis Cluster
redis.clusterserver=${mvn.redis.clusterserver}

 

在JedisClusterHelper中添加

public void flushDB(){
		String[] clusterServers = this.clusterServers.split(",");
		for(String clusterServer:clusterServers){
			Jedis jedis = jedisCluster.getClusterNodes().get(clusterServer).getResource();			
			jedis.flushDB();
		}
	}
	
	public Set<byte[]> keys(String pattern){
		Set<byte[]> keys = null;
		keys.add("begin".getBytes());
		String[] clusterServers = this.clusterServers.split(",");
		for(String clusterServer:clusterServers){
			Jedis jedis = jedisCluster.getClusterNodes().get(clusterServer).getResource();			
			 boolean isBroken = false;
				try{
					Set<byte[]> tempKeys = jedis.keys(pattern.getBytes());
					keys.addAll(tempKeys);
				}catch(Exception e){
		            isBroken = true;
				}finally{
//					returnResource(jedis, isBroken);
				}
			
		}
		keys.remove("begin".getBytes());
		return keys;
	}

 

ShiroSessionRepository

package com.csair.csmbp.web.common.shiro.session;


import org.apache.shiro.session.Session;
import java.io.Serializable;
import java.util.Collection;


public interface ShiroSessionRepository {

	 void saveSession(Session session);

	 void deleteSession(Serializable sessionId);

	 Session getSession(Serializable sessionId);

	 Collection<Session> getAllSessions();
	
}

 

ShiroSessionDAO

package com.csair.csmbp.web.common.shiro.session.impl;

import java.io.Serializable;
import java.util.Collection;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.UnknownSessionException;
import org.apache.shiro.session.mgt.eis.AbstractSessionDAO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.csair.csmbp.web.common.shiro.session.ShiroSessionRepository;

public class ShiroSessionDAO extends AbstractSessionDAO {
	
	private Logger logger = LoggerFactory.getLogger(getClass());
	private ShiroSessionRepository shiroSessionRepository;

	public ShiroSessionRepository getShiroSessionRepository() {
		return shiroSessionRepository;
	}

	public void setShiroSessionRepository(
			ShiroSessionRepository shiroSessionRepository) {
		this.shiroSessionRepository = shiroSessionRepository;
	}

	@Override
	public void delete(Session session) {
		// TODO Auto-generated method stub
		  if (session == null) {
	            return;
	        }
	        Serializable id = session.getId();
	        if (id != null) {	        	
	        	logger.info("delete session----:"+id);
	        	getShiroSessionRepository().deleteSession(id);
	        }
	}

	@Override
	public Collection<Session> getActiveSessions() {
		// TODO Auto-generated method stub
		return getShiroSessionRepository().getAllSessions();
	}

	@Override
	public void update(Session session) throws UnknownSessionException {
		// TODO Auto-generated method stub		
		logger.info("update session----更新:"+session.getId());
		getShiroSessionRepository().saveSession(session);
	}

	@Override
	protected Serializable doCreate(Session session) {
		// TODO Auto-generated method stub
		Serializable sessionId = this.generateSessionId(session);
        this.assignSessionId(session, sessionId);
        getShiroSessionRepository().saveSession(session);        
        logger.info("do create session----建完后:"+sessionId);
        return sessionId;
	}

	@Override
	protected Session doReadSession(Serializable sessionId) {
		// TODO Auto-generated method stub		
//		logger.info("do read session----参数:"+sessionId); 
		return getShiroSessionRepository().getSession(sessionId);
	}

}

 

BaseController中添加

protected void setSessionAttribute(String key,Object obj){
		Subject currentUser = SecurityUtils.getSubject();
		Session session = currentUser.getSession();
		session.setAttribute(key, obj);
	}
	
	protected Object getSessionAttribute(String key){
		Subject currentUser = SecurityUtils.getSubject();
		Session session = currentUser.getSession();
		return session.getAttribute(key);
	}

 

在普通的controller中调用

@RequestMapping(value = "test/setRedisSession.do")//test/zooKeeper.do?key=test
	@ResponseBody
	public void setSessionValue(){
		setSessionAttribute("TESTSESSION", "mysession");
		
		logger.info("TESTSESSION==========" + (String)getSessionAttribute("TESTSESSION"));
	}

 

 

 

 

分享到:
评论
3 楼 edwardsai 2017-11-11  
楼主,我第一次接触shiro,现在我们项目是用的是redis集群+shiro+springMvc,情况跟你这个项目应该一样的。但是现在出现2个问题
1、redis集群获取resource老是超时的问题(不知道是否跟搭建集群有关)
2、缓存在redis上的session缓存不知道如何删除(只能等他超时),因为shiro那里只是简单粗暴的配置了filterChainDefinitions的登出清空session,并没有把redis上的session也删掉。
请问楼主能否解答一下我的问题。顺便能否提供一下你这个项目shiro登录验证,登出清空session与redis的代码啊?
先感谢了
2 楼 phipray 2016-10-06  
wos12345 写道
楼主,这里你既然用了redis,为什么还要ehcache做缓存?楼主可否把整个项目的代码给我


我只是用redis来做shiro的sessionDB,其他的还是按原本shiro的配置
1 楼 wos12345 2016-05-16  
楼主,这里你既然用了redis,为什么还要ehcache做缓存?楼主可否把整个项目的代码给我

相关推荐

Global site tag (gtag.js) - Google Analytics