Skip to content

Instantly share code, notes, and snippets.

@repoplus
Created June 20, 2016 05:45
Show Gist options
  • Save repoplus/09c41013993599fb3c8b5e7fbcd52367 to your computer and use it in GitHub Desktop.
Save repoplus/09c41013993599fb3c8b5e7fbcd52367 to your computer and use it in GitHub Desktop.
shiro配置

spring

<?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>

CustomShiroSessionDAO

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

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment