shiro redis 集群 session无法登陆

吃不饱 发布于 2016/09/13 20:52
阅读 1K+
收藏 2

 登陆时2个tomcat打印的sessionid是一样的,可是redis没有。跟踪了一下代码刚开始进入doReadSession方法查询redis无数据后就报错了 org.apache.shiro.session.UnknownSessionException: There is no session with id【xxxxx】然后跳转到doCreate方法生成新的sessionid。就登陆不了 不知道哪里出错了。

我的配置

applicationContext-shiro.xml

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
		http://www.springframework.org/schema/beans/spring-beans-3.2.xsd 
		http://www.springframework.org/schema/mvc 
		http://www.springframework.org/schema/mvc/spring-mvc-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/aop 
		http://www.springframework.org/schema/aop/spring-aop-3.2.xsd 
		http://www.springframework.org/schema/tx 
		http://www.springframework.org/schema/tx/spring-tx-3.2.xsd 
		http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd" default-lazy-init="false">
<!-- 用户服务接口 -->

<!-- web.xml中shiro的filter对应的bean -->
<!-- Shiro 的Web过滤器 -->
	<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
		<property name="securityManager" ref="securityManager" />
		<!-- loginUrl认证提交地址,如果没有认证将会请求此地址进行认证,请求此地址将由formAuthenticationFilter进行表单认证 -->
		<property name="loginUrl" value="/login.do" />
		<!-- 认证成功统一跳转到first.action,建议不配置,shiro认证成功自动到上一个请求路径 -->
		<property name="successUrl" value="/successLogin.do"/>
		<!-- 通过unauthorizedUrl指定没有权限操作时跳转页面-->
		<property name="unauthorizedUrl" value="/refuse.do" />
		
		<!-- 过虑器链定义,从上向下顺序执行,一般将/**放在最下边 -->
		<property name="filterChainDefinitions">
			<value>
			    /**/images/** = anon
			    /**/script/** = anon
			    /**/style/**  = anon 
			    /logins.do = anon 
				<!-- 请求 logout.action地址,shiro去清除session
				/logout.do = logout -->
				<!-- /** = authc 所有url都必须认证通过才可以访问  query delete update add-->
				/** = authc
				<!-- /** = anon所有url都可以匿名访问 -->
				
			</value>
		</property>
	</bean>

<!-- securityManager安全管理器 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
		<property name="realm" ref="customRealm" />
		<!-- 注入session管理器 -->
		<property name="sessionManager" ref="sessionManager" />
         <!-- cacheManager -->
       <property name="cacheManager" ref="cacheManager" />
</bean>

<!-- realm -->
<bean id="customRealm" class="com.zefu.portal.login.controller.CustomRealm">
	<!-- 将凭证匹配器设置到realm中,realm按照凭证匹配器的要求进行散列 -->
    <property name="userService" ref="userService"/>
	<property name="credentialsMatcher" ref="credentialsMatcher"/>
</bean>

<!-- 凭证匹配器 -->
<bean id="credentialsMatcher"
	class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
	<property name="hashAlgorithmName" value="md5" />
	<property name="hashIterations" value="1" />
</bean>
<!-- 缓存管理器 -->
<bean id="eacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
    	<property name="cacheManagerConfigFile" value="classpath:shiro-ehcache.xml"/>
</bean>
<!-- 会话管理器 -->
<!--  <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
        删除失效的session
        <property name="deleteInvalidSessions" value="true"/>
         session的失效时长,单位毫秒 3600000ms 一小时
        <property name="globalSessionTimeout" value="3600000"/>
        相隔多久检查一次session的有效性
        <property name="sessionValidationInterval" value="1800000" /> 
        <property name="sessionValidationSchedulerEnabled" value="true" />
  </bean> -->
  
 <!-- Shiro生命周期处理器-->  
 <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>  
 
 <!-- shiro redisManager -->
 <bean id="redisManager" class="com.zefu.portal.login.controller.RedisManager">
    <property name="host" value="192.168.0.31"/>
    <property name="port" value="6379"/>
    <property name="expire" value="1800"/>
    <!-- optional properties:
    <property name="timeout" value="10000"/>
    <property name="password" value="123456"/>
    -->
</bean>
<!-- 会话DAO -->
<bean id="redisSessionDAO" class="com.zefu.portal.login.controller.RedisSessionDAO">
    <property name="redisManager" ref="redisManager" />
</bean>
<!-- 会话管理器 -->
<bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
    <property name="sessionDAO" ref="redisSessionDAO" />
    <property name="globalSessionTimeout" value="1800000" />
	<property name="deleteInvalidSessions" value="true" />
	<property name="sessionValidationSchedulerEnabled" value="false" />
</bean>
<!-- 缓存管理器 -->
<bean id="cacheManager" class="com.zefu.portal.login.controller.RedisCacheManager">
    <property name="redisManager" ref="redisManager" />
</bean>

</beans>



RedisCache.java

package com.zefu.portal.login.controller;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import org.apache.shiro.util.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class RedisCache<K, V> implements Cache<K, V> {
	
	private Logger logger = LoggerFactory.getLogger(this.getClass());
		
	/**
     * The wrapped Jedis instance.
     */
	private RedisManager cache;
	
	/**
	 * The Redis key prefix for the sessions 
	 */
	private String keyPrefix = "shiro_redis_session:";
	
	/**
	 * Returns the Redis session keys
	 * prefix.
	 * @return The prefix
	 */
	public String getKeyPrefix() {
		return keyPrefix;
	}

	/**
	 * Sets the Redis sessions key 
	 * prefix.
	 * @param keyPrefix The prefix
	 */
	public void setKeyPrefix(String keyPrefix) {
		this.keyPrefix = keyPrefix;
	}
	
	/**
	 * 通过一个JedisManager实例构造RedisCache
	 */
	public RedisCache(RedisManager cache){
		 if (cache == null) {
	         throw new IllegalArgumentException("Cache argument cannot be null.");
	     }
	     this.cache = cache;
	}
	
	/**
	 * Constructs a cache instance with the specified
	 * Redis manager and using a custom key prefix.
	 * @param cache The cache manager instance
	 * @param prefix The Redis key prefix
	 */
	public RedisCache(RedisManager cache, 
				String prefix){
		 
		this( cache );
		
		// set the prefix
		this.keyPrefix = prefix;
	}
	
	/**
	 * 获得byte[]型的key
	 * @param key
	 * @return
	 */
	private byte[] getByteKey(K key){
		if(key instanceof String){
			String preKey = this.keyPrefix + key;
    		return preKey.getBytes();
    	}else{
    		return SerializeUtils.serialize(key);
    	}
	}
 	
	@Override
	public V get(K key) throws CacheException {
		logger.debug("根据key从Redis中获取对象 key [" + key + "]");
		try {
			if (key == null) {
	            return null;
	        }else{
	        	byte[] rawValue = cache.get(getByteKey(key));
	        	@SuppressWarnings("unchecked")
				V value = (V)SerializeUtils.deserialize(rawValue);
	        	return value;
	        }
		} catch (Throwable t) {
			throw new CacheException(t);
		}

	}

	@Override
	public V put(K key, V value) throws CacheException {
		logger.debug("根据key从存储 key [" + key + "]");
		 try {
			 	cache.set(getByteKey(key), SerializeUtils.serialize(value));
	            return value;
	        } catch (Throwable t) {
	            throw new CacheException(t);
	        }
	}

	@Override
	public V remove(K key) throws CacheException {
		logger.debug("从redis中删除 key [" + key + "]");
		try {
            V previous = get(key);
            cache.del(getByteKey(key));
            return previous;
        } catch (Throwable t) {
            throw new CacheException(t);
        }
	}

	@Override
	public void clear() throws CacheException {
		logger.debug("从redis中删除所有元素");
		try {
            cache.flushDB();
        } catch (Throwable t) {
            throw new CacheException(t);
        }
	}

	@Override
	public int size() {
		try {
			Long longSize = new Long(cache.dbSize());
            return longSize.intValue();
        } catch (Throwable t) {
            throw new CacheException(t);
        }
	}

	@SuppressWarnings("unchecked")
	@Override
	public Set<K> keys() {
		try {
            Set<byte[]> keys = cache.keys(this.keyPrefix + "*");
            if (CollectionUtils.isEmpty(keys)) {
            	return Collections.emptySet();
            }else{
            	Set<K> newKeys = new HashSet<K>();
            	for(byte[] key:keys){
            		newKeys.add((K)key);
            	}
            	return newKeys;
            }
        } catch (Throwable t) {
            throw new CacheException(t);
        }
	}

	@Override
	public Collection<V> values() {
		try {
            Set<byte[]> keys = cache.keys(this.keyPrefix + "*");
            if (!CollectionUtils.isEmpty(keys)) {
                List<V> values = new ArrayList<V>(keys.size());
                for (byte[] key : keys) {
                    @SuppressWarnings("unchecked")
					V value = get((K)key);
                    if (value != null) {
                        values.add(value);
                    }
                }
                return Collections.unmodifiableList(values);
            } else {
                return Collections.emptyList();
            }
        } catch (Throwable t) {
            throw new CacheException(t);
        }
	}

}

RedisCacheManager

package com.zefu.portal.login.controller;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import org.apache.shiro.cache.CacheManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class RedisCacheManager implements CacheManager {

	private static final Logger logger = LoggerFactory
			.getLogger(RedisCacheManager.class);

	// fast lookup by name map
	private final ConcurrentMap<String, Cache> caches = new ConcurrentHashMap<String, Cache>();

	private RedisManager redisManager;

	/**
	 * The Redis key prefix for caches 
	 */
	private String keyPrefix = "shiro_redis_cache:";
	
	/**
	 * Returns the Redis session keys
	 * prefix.
	 * @return The prefix
	 */
	public String getKeyPrefix() {
		return keyPrefix;
	}

	/**
	 * Sets the Redis sessions key 
	 * prefix.
	 * @param keyPrefix The prefix
	 */
	public void setKeyPrefix(String keyPrefix) {
		this.keyPrefix = keyPrefix;
	}
	
	@Override
	public <K, V> Cache<K, V> getCache(String name) throws CacheException {
		logger.debug("获取名称为: " + name + " 的RedisCache实例");
		
		Cache c = caches.get(name);
		
		if (c == null) {

			// initialize the Redis manager instance
			redisManager.init();
			
			// create a new cache instance
			c = new RedisCache<K, V>(redisManager, keyPrefix);
			
			// add it to the cache collection
			caches.put(name, c);
		}
		return c;
	}

	public RedisManager getRedisManager() {
		return redisManager;
	}

	public void setRedisManager(RedisManager redisManager) {
		this.redisManager = redisManager;
	}

}



RedisManager

package com.zefu.portal.login.controller;

import java.util.Set;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

public class RedisManager {
	
	private String host = "127.0.0.1";
	
	private int port = 6379;
	
	// 0 - never expire
	private int expire = 0;
	
	//timeout for jedis try to connect to redis server, not expire time! In milliseconds
	private int timeout = 0;
	
	private String password = "";
	
	private static JedisPool jedisPool = null;
	
	public RedisManager(){
		
	}
	
	/**
	 * 初始化方法
	 */
	public void init(){
		if(jedisPool == null){
			if(password != null && !"".equals(password)){
				jedisPool = new JedisPool(new JedisPoolConfig(), host, port, timeout, password);
			}else if(timeout != 0){
				jedisPool = new JedisPool(new JedisPoolConfig(), host, port,timeout);
			}else{
				jedisPool = new JedisPool(new JedisPoolConfig(), host, port);
			}
			
		}
	}
	
	/**
	 * get value from redis
	 * @param key
	 * @return
	 */
	public byte[] get(byte[] key){
		byte[] value = null;
		Jedis jedis = jedisPool.getResource();
		try{
			value = jedis.get(key);
		}finally{
			jedisPool.returnResource(jedis);
		}
		return value;
	}
	
	/**
	 * set 
	 * @param key
	 * @param value
	 * @return
	 */
	public byte[] set(byte[] key,byte[] value){
		Jedis jedis = jedisPool.getResource();
		try{
			jedis.set(key,value);
			if(this.expire != 0){
				jedis.expire(key, this.expire);
		 	}
		}finally{
			jedisPool.returnResource(jedis);
		}
		return value;
	}
	
	/**
	 * set 
	 * @param key
	 * @param value
	 * @param expire
	 * @return
	 */
	public byte[] set(byte[] key,byte[] value,int expire){
		Jedis jedis = jedisPool.getResource();
		try{
			jedis.set(key,value);
			if(expire != 0){
				jedis.expire(key, expire);
		 	}
		}finally{
			jedisPool.returnResource(jedis);
		}
		return value;
	}
	
	/**
	 * del
	 * @param key
	 */
	public void del(byte[] key){
		Jedis jedis = jedisPool.getResource();
		try{
			jedis.del(key);
		}finally{
			jedisPool.returnResource(jedis);
		}
	}
	
	/**
	 * flush
	 */
	public void flushDB(){
		Jedis jedis = jedisPool.getResource();
		try{
			jedis.flushDB();
		}finally{
			jedisPool.returnResource(jedis);
		}
	}
	
	/**
	 * size
	 */
	public Long dbSize(){
		Long dbSize = 0L;
		Jedis jedis = jedisPool.getResource();
		try{
			dbSize = jedis.dbSize();
		}finally{
			jedisPool.returnResource(jedis);
		}
		return dbSize;
	}

	/**
	 * keys
	 * @param regex
	 * @return
	 */
	public Set<byte[]> keys(String pattern){
		Set<byte[]> keys = null;
		Jedis jedis = jedisPool.getResource();
		try{
			keys = jedis.keys(pattern.getBytes());
		}finally{
			jedisPool.returnResource(jedis);
		}
		return keys;
	}
	
	public String getHost() {
		return host;
	}

	public void setHost(String host) {
		this.host = host;
	}

	public int getPort() {
		return port;
	}

	public void setPort(int port) {
		this.port = port;
	}

	public int getExpire() {
		return expire;
	}

	public void setExpire(int expire) {
		this.expire = expire;
	}

	public int getTimeout() {
		return timeout;
	}

	public void setTimeout(int timeout) {
		this.timeout = timeout;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}
	
	
	
}



RedisSessionDAO

package com.zefu.portal.login.controller;

import java.io.Serializable;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

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;

public class RedisSessionDAO extends AbstractSessionDAO {

	private static Logger logger = LoggerFactory.getLogger(RedisSessionDAO.class);
	/**
	 * shiro-redis的session对象前缀
	 */
	private RedisManager redisManager;
	
	/**
	 * The Redis key prefix for the sessions 
	 */
	private String keyPrefix = "shiro_redis_session:";
	
	@Override
	public void update(Session session) throws UnknownSessionException {
		this.saveSession(session);
	}
	
	/**
	 * save session
	 * @param session
	 * @throws UnknownSessionException
	 */
	private void saveSession(Session session) throws UnknownSessionException{
		if(session == null || session.getId() == null){
			logger.error("session or session id is null");
			return;
		}
		
		byte[] key = getByteKey(session.getId());
		byte[] value = SerializeUtils.serialize(session);
		session.setTimeout(redisManager.getExpire()*1000);		
		this.redisManager.set(key, value, redisManager.getExpire());
	}

	@Override
	public void delete(Session session) {
		if(session == null || session.getId() == null){
			logger.error("session or session id is null");
			return;
		}
		redisManager.del(this.getByteKey(session.getId()));
       System.out.println("redisManager======delete:"+session.getId()+"==================");
	}

	@Override
	public Collection<Session> getActiveSessions() {
		Set<Session> sessions = new HashSet<Session>();
		
		Set<byte[]> keys = redisManager.keys(this.keyPrefix + "*");
		if(keys != null && keys.size()>0){
			for(byte[] key:keys){
				Session s = (Session)SerializeUtils.deserialize(redisManager.get(key));
				sessions.add(s);
			}
		}
		
		return sessions;
	}

	@Override
	protected Serializable doCreate(Session session) {
		Serializable sessionId = this.generateSessionId(session);  
        this.assignSessionId(session, sessionId);
        this.saveSession(session);
		return sessionId;
	}

	@Override
	protected Session doReadSession(Serializable sessionId) {
		if(sessionId == null){
			logger.error("session id is null");
			return null;
		}
		
		Session s = (Session)SerializeUtils.deserialize(redisManager.get(this.getByteKey(sessionId)));
		return s;
	}
	
	/**
	 * 获得byte[]型的key
	 * @param key
	 * @return
	 */
	private byte[] getByteKey(Serializable sessionId){
		String preKey = this.keyPrefix + sessionId;
		return preKey.getBytes();
	}

	public RedisManager getRedisManager() {
		return redisManager;
	}

	public void setRedisManager(RedisManager redisManager) {
		this.redisManager = redisManager;
		
		/**
		 * 初始化redisManager
		 */
		this.redisManager.init();
	}

	/**
	 * Returns the Redis session keys
	 * prefix.
	 * @return The prefix
	 */
	public String getKeyPrefix() {
		return keyPrefix;
	}

	/**
	 * Sets the Redis sessions key 
	 * prefix.
	 * @param keyPrefix The prefix
	 */
	public void setKeyPrefix(String keyPrefix) {
		this.keyPrefix = keyPrefix;
	}
	
	
}



CustomRealm

package com.zefu.portal.login.controller;

import java.util.ArrayList;
import java.util.List;



import org.apache.shiro.SecurityUtils;
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.authc.UnknownAccountException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;

import com.zefu.portal.bean.system.Permission;
import com.zefu.portal.bean.system.User;
import com.zefu.portal.services.menu.MenuService;
import com.zefu.portal.services.permission.UserService;

public class CustomRealm extends AuthorizingRealm {
	

	private UserService userService;
 
	private MenuService menuService;

	// 设置realm的名称
	@Override
	public void setName(String name) {
		super.setName("customRealm");
	}

	//realm的认证方法,从数据库查询用户信息
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(
			AuthenticationToken token) throws AuthenticationException {	
		// token是用户输入的用户名和密码 
		// 第一步从token中取出用户名
		String name = (String) token.getPrincipal();
		// 第二步:根据用户输入的userCode从数据库查询
		User sysUser = null;
    	try {
			sysUser = userService.findUserInfo(name);
		} catch (Exception e1) {
			e1.printStackTrace();
		}
		// 如果查询不到返回null
		if(sysUser==null){
			throw new UnknownAccountException();
	
		}
		// 从数据库查询到密码
		String password = sysUser.getPassword();
		//盐
		String salt = sysUser.getUsername();

		//将activeUser设置simpleAuthenticationInfo
		SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(
				sysUser, password, ByteSource.Util.bytes(salt),this.getName());
		return simpleAuthenticationInfo;
	}
	
	

	// 用于授权
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(
			PrincipalCollection principals) {
		//从 principals获取主身份信息
		//将getPrimaryPrincipal方法返回值转为真实身份类型(在上边的doGetAuthenticationInfo认证通过填充到SimpleAuthenticationInfo中身份类型),
		User user =  (User) principals.getPrimaryPrincipal();
		//根据身份信息获取权限信息
		//从数据库获取到权限数据
		List<Permission> permissionList = null;
		try {
			permissionList = userService.getPermissions(user.getRole().getRoleId());
		} catch (Exception e) {
			e.printStackTrace();
		}
		//单独定一个集合对象 
		List<String> permissions = new ArrayList<String>();
		if(permissionList!=null){
			for(Permission sysPermission:permissionList){
				if(sysPermission!=null){
				  //将数据库中的权限标签 符放入集合
				  permissions.add(sysPermission.getElementId());
				}
			}
		}
		
		//查到权限数据,返回授权信息(要包括 上边的permissions)
		SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
		//将上边查询到授权信息填充到simpleAuthorizationInfo对象中
		simpleAuthorizationInfo.addStringPermissions(permissions);

		return simpleAuthorizationInfo;
	}
	
	//清除缓存
	public void clearCached() {
		PrincipalCollection principals = SecurityUtils.getSubject().getPrincipals();
		super.clearCache(principals);
	}

	public UserService getUserService() {
		return userService;
	}

	public void setUserService(UserService userService) {
		this.userService = userService;
	}

	public MenuService getMenuService() {
		return menuService;
	}

	public void setMenuService(MenuService menuService) {
		this.menuService = menuService;
	}




}



LoginController

package com.zefu.portal.login.controller;

import java.net.InetAddress;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.DisabledAccountException;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.ExpiredCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.UnauthorizedException;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import com.zefu.portal.annotation.SystemControllerLog;
import com.zefu.portal.bean.system.Menu;
import com.zefu.portal.bean.system.User;
import com.zefu.portal.services.menu.MenuService;
import com.zefu.portal.services.permission.RoleService;
import com.zefu.portal.util.StringUtils;




/**
 * 登入控制器
 */
@Controller
@RequestMapping("/")
public class LoginController {
	@Autowired
	private MenuService menuService;
	
	@Autowired
	private RoleService roleService;

	@RequestMapping(value = "login")
	public String LogginGet() {
		return "/login/login.jsp";
	}


	@RequestMapping("logins")
	public String login(User user, ModelMap map, HttpServletRequest request,HttpServletResponse httpresponse) {

		// 根据shiro返回的异常类路径判断,抛出指定异常信息
		String msg = "";
		Subject subject = SecurityUtils.getSubject();
		String name=user.getUsername();
		String password=user.getPassword();
		UsernamePasswordToken token = new UsernamePasswordToken(name, password);
        if(StringUtils.isEmpty(name)||StringUtils.isEmpty(password)){
        	msg = "用户名或密码不能为空";
			map.addAttribute("msg", msg);
			return "/login/login.jsp";
        }
      
		
		try {
    			subject.login(token);
    	}/*catch (RpcException e){
    		msg = "与服务器连接失败,请联系管理员";
			map.addAttribute("msg", msg);
			return "/login/login.jsp";
    		
    	}*//**/
		catch ( UnknownAccountException uae ) {   
			msg = "用户名或密码错误.";
			map.addAttribute("msg", msg);
			return "/login/login.jsp";
		} catch (ExcessiveAttemptsException e) {
			msg = "登录失败次数过多";
			map.addAttribute("msg", msg);
			return "/login/login.jsp";
		} catch (LockedAccountException e) {
			msg = "帐号已被锁定.";
			map.addAttribute("msg", msg);
			return "/login/login.jsp";
		} catch (DisabledAccountException e) {
			msg = "帐号已被禁用.";
			map.addAttribute("msg", msg);
			return "/login/login.jsp";
		} catch (ExpiredCredentialsException e) {
			msg = "帐号已过期. ";
			map.addAttribute("msg", msg);
			return "/login/login.jsp";
		} catch (UnauthorizedException e) {
			msg = "您没有得到相应的授权!" + e.getMessage();
			map.addAttribute("msg", msg);
			return "/login/login.jsp";

		} catch (AuthenticationException e) {
    		msg = "用户名或密码错误";
    		map.addAttribute("msg", msg);
    		return "/login/login.jsp";
    	} 
	

		return "redirect:/successLogin.do";
		
		
	}
	

   /**
    * 
    * 功能描述:(无权访问跳转方法)
    * @author linjm  
    * @date  2015年12月27日 下午3:18:35
    *
    * @param  @return
    * @param  @throws Exception   
    * @return String 
    * @mender (修改者)
    * @update(修改内容-简单描述)
    * @updatetime(修改时间)
    */
	@RequestMapping("refuse")
   public String refuse()throws Exception{
		//重定向到登录页面
		return "/refuse.jsp";
		
	}
	/**
	    * 
	    * 功能描述:(权限认证后加载页面)
	    * @author linjm  
	    * @date  2015年12月27日 下午3:18:35
	    *
	    * @param  @return
	    * @param  @throws Exception   
	    * @return String 
	    * @mender (修改者)
	    * @update(修改内容-简单描述)
	    * @updatetime(修改时间)
	    */
	@RequestMapping("successLogin")
	@SystemControllerLog(description="登陆管理-成功登陆")
	public String successLogin() {
		 Subject currentUser = SecurityUtils.getSubject();
		 //将用户信息和菜单信息存放在session中
		  Session session = currentUser.getSession();
		  User user=(User) currentUser.getPrincipal();
		  String roleName=roleService.getRole(user.getRole()).getName();
		  List<Menu> menus=null;
		  if(roleName.equals("超级管理员")){
			   menus  = menuService.getRootMenus();
		  }else{
			   menus  = menuService.getMenus(user.getRole().getRoleId());
		  }
		  session.setAttribute("menus", menus);
		  session.setAttribute("user", user);
		  
		  InetAddress ia=null;
			try {
				ia=ia.getLocalHost();
				
				String localname=ia.getHostName();
				String localip=ia.getHostAddress();
				System.out.println("#############本机名称是:"+ localname);
				System.out.println("######################本机的ip是 :"+localip);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		  
		  
		return "/index_ims.jsp";
	}
    
	@RequestMapping("outLogin")
	public String outLogin(HttpServletResponse httpresponse) {
		 Subject subject = SecurityUtils.getSubject();
		
/*		  User user=(User) subject.getPrincipal();
			if(user!=null){
				Cookie cookie = new Cookie("user", null);
				cookie.setMaxAge(0); // 如果参数是0,就说明立即删除
				httpresponse.addCookie(cookie);
			}*/
			if (subject != null) {
				subject.logout();
			} 
		 return "/login/login.jsp";
	}
	/**
	    * 
	    * 功能描述:(手动清楚缓存)
	    * @author linjm  
	    * @date  2015年12月27日 下午3:18:35
	    *
	    * @param  @return
	    * @param  @throws Exception   
	    * @return String 
	    * @mender (修改者)
	    * @update(修改内容-简单描述)
	    * @updatetime(修改时间)
	    */
/*	@RequestMapping("clearShiroCache")
	public String clearShiroCache(){
		
		//清除缓存,将来正常开发要在service调用customRealm.clearCached()
		customRealm.clearCached();
		
		return "success";
	}*/

}





加载中
0
爱生活-爱美女
爱生活-爱美女

 <!-- sessionIdCookie的实现,用于重写覆盖容器默认的JSESSIONID -->  
    <bean id="sharesession" class="org.apache.shiro.web.servlet.SimpleCookie">  
        <!-- cookie的name,对应的默认是 JSESSIONID -->  
        <constructor-arg name="name" value="SHAREJSESSIONID" />  
        <!-- jsessionId的path为 / 用于多个系统共享jsessionId -->  
        <property name="path" value="/" />  
        <property name="httpOnly" value="true"/>  
    </bean>  
<!-- sessionManager -->
<bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
<!-- 设置全局会话超时时间,默认30分钟(1800000) -->  
        <property name="globalSessionTimeout" value="1800000" />  
        <!-- 是否在会话过期后会调用SessionDAO的delete方法删除会话 默认true -->  
        <property name="deleteInvalidSessions" value="true" />  
        <!-- 会话验证器调度时间 -->  
        <property name="sessionValidationInterval" value="1800000" />  
        <!-- session存储的实现 -->  
        <property name="sessionDAO" ref="redisSessionDAO" />  
        <!-- sessionIdCookie的实现,用于重写覆盖容器默认的JSESSIONID -->  
        <property name="sessionIdCookie" ref="sharesession" />  
        <!-- 定时检查失效的session -->  
        <property name="sessionValidationSchedulerEnabled" value="true" />  
</bean>

复写JSESSIONID  同时 由于shiro 的原因 你会发现 系统访问一次url 会多次调用doReadSession方法 产生大量的redis io读取,建议在doReadSession方法添加二级缓存~


爱生活-爱美女
爱生活-爱美女
回复 @吃不饱 : 可尝试一下google的guava
吃不饱
吃不饱
大神有 doReadSession 二级缓存的思路吗和资料吗
0
loyal
loyal
你用ehcache了,那么问题来了,你ehcache做集群配置了吗?
吃不饱
吃不饱
ehcahe 没做集群,目前这问题还没涉及到ehcahe我连登陆都登不了
0
吃不饱
吃不饱
@全体 大神们帮帮忙
0
吃不饱
吃不饱
单机是先进sava sessionId方法 在进doReadSession可以正常登录,集群是先进doReadSession方法导致获取sessionId和保存的id不一样 大神们怎么解?
返回顶部
顶部