<?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:context="http://www.springframework.org/schema/context" xmlns:util="http://www.springframework.org/schema/util" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-3.2.xsd" default-lazy-init="true">
<description>Shiro安全配置</description>
<!-- Shiro的主要业务层对象基于web的应用程序 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="myRealm" />
<!-- 单机环境下缓存配置 -->
<property name="cacheManager" ref="shiroEhcacheManager" />
<!-- 集群环境下缓存配置 -->
<!-- <property name="cacheManager" ref="customShiroCacheManager" /> -->
<property name="sessionManager" ref="sessionManager" />
<property name="rememberMeManager" ref="rememberMeManager" />
</bean>
<!-- 会话管理器 -->
<bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
<property name="globalSessionTimeout" value="1800000" />
<property name="deleteInvalidSessions" value="true" />
<property name="sessionIdCookieEnabled" value="true" />
<property name="sessionIdCookie" ref="sessionIdCookie" />
<!-- 单机环境下不需要注入 -->
<!-- <property name="sessionDAO" ref="customShiroSessionDAO"/> -->
</bean>
<!-- 单机环境下不需要注入 -->
<bean id="customShiroSessionDAO" class="com.muze.core.app.session.cluster.CustomShiroSessionDAO">
<property name="shiroSessionRepository" ref="jedisShiroSessionRepository" />
</bean>
<!-- custom save session by redis class impl ShiroSessionRepository interface -->
<bean id="jedisShiroSessionRepository" class="com.muze.core.app.session.cluster.JedisShiroSessionRepository">
<property name="jedisManager" ref="jedisManager" />
</bean>
<!-- redis manager class -->
<bean id="jedisManager" class="com.muze.core.app.redis.JedisManager">
<property name="jedisPool" ref="jedisPool" />
</bean>
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxActive" value="${muze.session.maxActive}" />
<property name="maxIdle" value="${muze.session.maxIdle}" />
<property name="minIdle" value="${muze.session.minIdle}" />
<property name="maxWait" value="${muze.session.maxWait}" />
<property name="testOnBorrow" value="true" />
<property name="testOnReturn" value="true" />
</bean>
<bean id="jedisPool" class="redis.clients.jedis.JedisPool">
<constructor-arg index="0" ref="jedisPoolConfig" />
<constructor-arg index="1" value="${muze.session.host}" />
<constructor-arg index="2" value="${muze.session.port}" />
<constructor-arg index="3" value="${muze.session.timeout}" />
<!-- <constructor-arg index="4" value="password"/> -->
</bean>
<!-- 会话Cookie模板 -->
<bean id="sessionIdCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
<constructor-arg value="sid" />
<property name="httpOnly" value="true" />
<property name="maxAge" value="-1" />
</bean>
<!-- rememberMe管理器 -->
<bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager">
<property name="cipherKey" value="#{T(org.apache.shiro.codec.Base64).decode('4AvVhmFLUs0KTA3Kprsdag==')}" />
<property name="cookie" ref="rememberMeCookie" />
</bean>
<bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
<constructor-arg value="rememberMe" />
<property name="httpOnly" value="true" />
<property name="maxAge" value="2592000" />
<!-- 30天 -->
</bean>
<!-- 相当于调用SecurityUtils.setSecurityManager(securityManager) -->
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="staticMethod" value="org.apache.shiro.SecurityUtils.setSecurityManager" />
<property name="arguments" ref="securityManager" />
</bean>
<bean id="myRealm" class="com.muze.core.app.login.shiro.MyRealm" />
<bean id="formAuthenticationFilter" class="org.apache.shiro.web.filter.authc.FormAuthenticationFilter" />
<!-- Shiro Filter -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager" />
<property name="loginUrl" value="/login/userLogin.do" />
<property name="successUrl" value="/" />
<property name="unauthorizedUrl" value="/login/unauthorized.do" />
<property name="filters">
<util:map>
<entry key="authc" value-ref="formAuthenticationFilter" />
</util:map>
</property>
<property name="filterChainDefinitions">
<value>
/login/** = anon
/css/** = anon
/easyui/** = anon
/icons/** = anon
/inc/** = anon
/js/** = anon
/** =authc
</value>
</property>
</bean>
<!-- 用户授权信息Cache, 采用EhCache ,非集群环境下 -->
<bean id="shiroEhcacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
<property name="cacheManagerConfigFile" value="classpath:spring/ehcache-shiro.xml" />
</bean>
<!-- cache集群环境下配置 -->
<!-- custom shiro authorization info cache manager class -->
<bean id="customShiroCacheManager" class="com.muze.core.app.cache.cluster.CustomShiroCacheManager">
<property name="shiroCacheManager" ref="jedisShiroCacheManager" />
</bean>
<!-- ShiroCacheManager interface impl class by redis,save authorization info to redis -->
<bean id="jedisShiroCacheManager" class="com.muze.core.app.cache.cluster.JedisShiroCacheManager">
<property name="jedisManager" ref="jedisManager" />
</bean>
<!-- 保证实现了Shiro内部lifecycle函数的bean执行 -->
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />
<!-- AOP式方法级权限检查 -->
<!-- <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>
package com.muze.core.app.session.cluster;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.UnknownSessionException;
import org.apache.shiro.session.mgt.eis.AbstractSessionDAO;
import java.io.Serializable;
import java.util.Collection;
/**
* custom shiro sessionDAO
*
* @author michael
*/
public class CustomShiroSessionDAO extends AbstractSessionDAO {
private ShiroSessionRepository shiroSessionRepository;
@Override
public void update(Session session) throws UnknownSessionException {
System.out.println("update session");
getShiroSessionRepository().saveSession(session);
}
@Override
public void delete(Session session) {
if (session == null) {
return;
}
Serializable id = session.getId();
if (id != null) {
System.out.println("delete session");
getShiroSessionRepository().deleteSession(id);
}
//TODO if session is too large,when session destory clear shiro cache
}
@Override
public Collection<Session> getActiveSessions() {
System.out.println("get active sessions");
return getShiroSessionRepository().getAllSessions();
}
@Override
protected Serializable doCreate(Session session) {
System.out.println("do create session");
Serializable sessionId = this.generateSessionId(session);
this.assignSessionId(session, sessionId);
getShiroSessionRepository().saveSession(session);
return sessionId;
}
@Override
protected Session doReadSession(Serializable sessionId) {
System.out.println("do read session");
return getShiroSessionRepository().getSession(sessionId);
}
public ShiroSessionRepository getShiroSessionRepository() {
return shiroSessionRepository;
}
public void setShiroSessionRepository(
ShiroSessionRepository shiroSessionRepository) {
this.shiroSessionRepository = shiroSessionRepository;
}
}
JedisShiroSessionRepository
package com.muze.core.app.session.cluster;
import java.io.Serializable;
import java.util.Collection;
import org.apache.shiro.session.Session;
import com.muze.core.app.redis.JedisManager;
import com.muze.core.app.utils.SerializeUtil;
/**
* redis save shiro session class
*
* @author michael
*/
public class JedisShiroSessionRepository implements ShiroSessionRepository {
private static final String REDIS_SHIRO_SESSION = "shiro-session:";
private static final int DB_INDEX = 0;
private JedisManager jedisManager;
@Override
public void saveSession(Session session) {
if (session == null || session.getId() == null)
throw new NullPointerException("session is empty");
try {
byte[] key = SerializeUtil.serialize(buildRedisSessionKey(session.getId()));
byte[] value = SerializeUtil.serialize(session);
long sessionTimeOut = session.getTimeout() / 1000;
/*Long expireTime = sessionTimeOut + SESSION_VAL_TIME_SPAN + (5 * 60);*/
Long expireTime=sessionTimeOut;
getJedisManager().saveValueByKey(DB_INDEX, key, value, expireTime.intValue());
} catch (Exception e) {
e.printStackTrace();
System.out.println("save session error");
}
}
@Override
public void deleteSession(Serializable id) {
if (id == null) {
throw new NullPointerException("session id is empty");
}
try {
getJedisManager().deleteByKey(DB_INDEX,
SerializeUtil.serialize(buildRedisSessionKey(id)));
} catch (Exception e) {
e.printStackTrace();
System.out.println("delete session error");
}
}
@Override
public Session getSession(Serializable id) {
if (id == null)
throw new NullPointerException("session id is empty");
Session session = null;
try {
byte[] value = getJedisManager().getValueByKey(DB_INDEX, SerializeUtil
.serialize(buildRedisSessionKey(id)));
session = SerializeUtil.deserialize(value, Session.class);
} catch (Exception e) {
e.printStackTrace();
System.out.println("get session error");
}
return session;
}
@Override
public Collection<Session> getAllSessions() {
//TODO
System.out.println("get all sessions");
return null;
}
private String buildRedisSessionKey(Serializable sessionId) {
return REDIS_SHIRO_SESSION + sessionId;
}
public JedisManager getJedisManager() {
return jedisManager;
}
public void setJedisManager(JedisManager jedisManager) {
this.jedisManager = jedisManager;
}
}
package com.muze.core.app.redis;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.exceptions.JedisConnectionException;
/**
* jedis manager
*
* @author michael
*/
public class JedisManager {
private JedisPool jedisPool;
public Jedis getJedis() {
Jedis jedis = null;
try {
jedis = getJedisPool().getResource();
} catch (Exception e) {
throw new JedisConnectionException(e);
}
return jedis;
}
public void returnResource(Jedis jedis, boolean isBroken) {
if (jedis == null)
return;
if (isBroken)
getJedisPool().returnBrokenResource(jedis);
else
getJedisPool().returnResource(jedis);
}
public byte[] getValueByKey(int dbIndex, byte[] key) throws Exception {
Jedis jedis = null;
byte[] result = null;
boolean isBroken = false;
try {
jedis = getJedis();
jedis.select(dbIndex);
result = jedis.get(key);
} catch (Exception e) {
isBroken = true;
throw e;
} finally {
returnResource(jedis, isBroken);
}
return result;
}
public void deleteByKey(int dbIndex, byte[] key) throws Exception {
Jedis jedis = null;
boolean isBroken = false;
try {
jedis = getJedis();
jedis.select(dbIndex);
jedis.del(key);
} catch (Exception e) {
isBroken = true;
throw e;
} finally {
returnResource(jedis, isBroken);
}
}
public void saveValueByKey(int dbIndex, byte[] key, byte[] value, int expireTime)
throws Exception {
Jedis jedis = null;
boolean isBroken = false;
try {
jedis = getJedis();
jedis.select(dbIndex);
jedis.set(key, value);
if (expireTime > 0)
jedis.expire(key, expireTime);
} catch (Exception e) {
isBroken = true;
throw e;
} finally {
returnResource(jedis, isBroken);
}
}
public JedisPool getJedisPool() {
return jedisPool;
}
public void setJedisPool(JedisPool jedisPool) {
this.jedisPool = jedisPool;
}
}