shiro实现不同浏览器本修改密码时其余浏览器需要重新登录

/**
 * 
* 类说明: session序列化工具
* @author 作者 LzwGlory
* @version 创建时间:2015年3月11日 上午11:36:35 
*
 */
public class SerializableUtils {

    public static String serialize(Session session) {
        try {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bos);
            oos.writeObject(session);
            return Base64.encodeToString(bos.toByteArray());
        } catch (Exception e) {
            throw new RuntimeException("serialize session error", e);
        }
    }
    public static Session deserialize(String sessionStr) {
        try {
            ByteArrayInputStream bis = new ByteArrayInputStream(Base64.decode(sessionStr));
            ObjectInputStream ois = new ObjectInputStream(bis);
            return (Session)ois.readObject();
        } catch (Exception e) {
            throw new RuntimeException("deserialize session error", e);
        }
    }
}

/**
 * @author lzwglory
 * @time 2015-3-11
 */
public class ShiroSecurityHelper {

	private static SessionDAO sessionDAO;

	/**
	 * 获得当前用户名
	 * 
	 * @return
	 */
	public static String getCurrentUsername() {
		Subject subject = getSubject();
		PrincipalCollection collection = subject.getPrincipals();
		if (null != collection && !collection.isEmpty()) {
			return (String) collection.iterator().next();
		}
		return null;
	}

	/**
	 * 
	 * @return
	 */
	public static Session getSession() {
		return SecurityUtils.getSubject().getSession();
	}

	/**
	 * 
	 * @return
	 */
	public static String getSessionId() {
		Session session = getSession();
		if (null == session) {
			return null;
		}
		return getSession().getId().toString();
	}

	/**
	 * @param username
	 * @return
	 */
	public static Session getSessionByUsername(String username) {
		Collection<Session> sessions = sessionDAO.getActiveSessions();
		for (Session session : sessions) {
			if (null != session
					&& StringUtils
							.equals(String
									.valueOf(session
											.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY)),
									username)) {
				return session;
			}
		}
		return null;
	}

	/**
	 * 判断当前用户是否已通过认证
	 * 
	 * @return
	 */
	public static boolean hasAuthenticated() {
		return getSubject().isAuthenticated();
	}

	public static void layout() {
		getSubject().logout();
	}

	private static Subject getSubject() {
		return SecurityUtils.getSubject();
	}

}

<?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: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/util 
    http://www.springframework.org/schema/util/spring-util-3.1.xsd ">
	<description>Shiro 配置</description>
	<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
		<property name="securityManager" ref="securityManager" />
		<property name="loginUrl" value="/login_txz.jsp" />
		<property name="successUrl" value="/homePage.jsp" />
		<property name="unauthorizedUrl" value="/error/noperms.jsp" />
		<property name="filters">
			<util:map>
				<entry key="userSetting" value-ref="userSettingFilter" />
				<entry key="myAdvice" value-ref="myAdviceFilter" />
			</util:map>
		</property>
		<property name="filterChainDefinitions">
			<value>
				/ = anon
				/*anon_* =anon
				/**/*anon_* =anon
				/**/*app_*.do* = anon
				/owsSSO*.do* = anon
				/login.jsp* = anon
				/login*.do* = anon
				/register.jsp* = anon
				/homePage.jsp* = anon
				/forgetpwd.jsp* = anon
				/login.do* = anon
				/register*.do* = anon
				/cipher*.do = anon
				/app/index.jsp*= anon

				/error/noperms.jsp*= anon
				/home.jsp= anon
				/sub_order.jsp*= anon
				/** = myAdvice
			</value>
		</property>
	</bean>

	<bean id="userSettingFilter" class="com.ultrapower.rw.web.ows.filter.UserSetting" />
	<bean id="myAdviceFilter" class="com.ultrapower.rw.web.ows.filter.MyAdviceFilter" />

	<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
		<!--设置自定义realm -->
		<property name="realm" ref="monitorRealm" />
		<property name="sessionManager" ref="sessionManager"/>
		<!-- <property name="sessionManager" ref="sessionManager"/> -->
		
	</bean>
	<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />

	<!--自定义Realm 继承自AuthorizingRealm -->
	<bean id="monitorRealm" class="com.ultrapower.rw.web.ows.service.MonitorRealm"></bean>
	<!-- start sessiondao -->
	<bean id="sessionManager"
		class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
		<property name="sessionDAO" ref="sessionDAO" />
		<property name="sessionIdCookie.name" value="jsid"/>  
	</bean>
	<bean id="sessionDAO"
		class="com.ultrapower.rw.web.ows.shiro.session.MySessionDAO" />
	<!-- end sessiondao -->
	<!-- securityManager -->
	<bean
		class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
		<property name="staticMethod"
			value="org.apache.shiro.SecurityUtils.setSecurityManager" />
		<property name="arguments" ref="securityManager" />
	</bean>

	<!-- Enable Shiro Annotations for Spring-configured beans. Only run after -->
	<!-- the lifecycleBeanProcessor has run: -->
	<bean
		class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
		depends-on="lifecycleBeanPostProcessor" />
	<bean
		class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
		<property name="securityManager" ref="securityManager" />
	</bean>
</beans>


/** 
 * @author 作者 LzwGlory
 * @version 创建时间:2015年3月12日 下午2:36:22 
 * 类说明 
 */
public enum ShiroType {

	flag();
	
	private ShiroType(){
		
	}
	/**
	 * 更改密码标示
	 */
	public final String isModifyPwd = "isModifyPwd_";
	
	/**
	 * 退出标示
	 */
	public final String isLayout = "isLayout_";
}


/**
 * @author 作者 LzwGlory
 * @version 创建时间:2015年3月4日 下午5:46:11 类说明 shiro session管理
 */
public class MySessionDAO extends CachingSessionDAO {

	private static Logger log = Logger.getLogger(LoginController.class);
	private static final Cache cache = CacheFactory
			.getCache(OwsConstant.USERDTOCACHE);

	private String keyPrefix = "shiro_session_";
	Set<String> jsidSet;

	public MySessionDAO() {
	}

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

	@Override
	protected Session doReadSession(Serializable sessionId) {
		try {
			// 先取出对应的session
			Object sessionObj = cache.get(sessionId.toString());
			if (sessionObj == null) {// 取出当为空时直接返回空
				return null;
			}
			// Session session = (Session) sessionObj;
			Session session = SerializableUtils.deserialize(String
					.valueOf(sessionObj));
			// 用于存储用户id对应的sessionid
			Object userIDObj = session.getAttribute("userId");
            
			if (ShiroSecurityHelper.hasAuthenticated()) {
//				if (userIDObj != null&&!"yes".equals(cache.get(ShiroType.flag.isLayout + String.valueOf(userIDObj)))) {
				// cache.get(session.getAttribute("userId").toString());
				// cache.remove(session.getAttribute("userId").toString());
				String userID = String.valueOf(userIDObj);
				String keyUserID = this.keyPrefix + userID;

				if ((Set<String>) cache.get(keyUserID) == null){
					jsidSet = new HashSet<String>();
				}else{
					jsidSet = (Set<String>) cache.get(keyUserID);
				}
				log.info("----size:" + jsidSet.size() + "-------jsidSet:"
						+ jsidSet);
				jsidSet.add(sessionId.toString());
				cache.set(keyUserID, jsidSet);
				// 如果修改密码成功后则直接清除除了当前的sessionid
				if (cache.get(ShiroType.flag.isModifyPwd + userID) != null) {
					String curJsid = String.valueOf(cache.get("isModifyPwd_"
							+ userID));
					jsidSet = (Set<String>) cache.get(keyUserID);
					for (String str : jsidSet) {
						if (!str.equals(curJsid)) {
							cache.remove(str);
						}
					}
					cache.remove("isModifyPwd_" + userID);
					// 当取出多余的session后重新取一下session
				}
			}
			return session;
			// String json = cache.get(MemcachedObjectType.SESSION.getPrefix() +
			// sessionId.toString());
			// return (Session) serializer.deserialize(Encodes.decodeHex(json));
		} catch (Exception e) {
			log.warn("## Not found session #{}" + sessionId);
			return null;
		}
	}

	@Override
	protected void doDelete(Session session) {
		// TODO Auto-generated method stub
		if (session == null) {
			throw new NullPointerException("session argument cannot be null.");
		}
		// 取出所有的当前账户对应的sessionid集合
		Object userIDObj=session.getAttribute("userId");
		if(userIDObj!=null){
			String userID = String.valueOf(userIDObj);
			String keyUserID = this.keyPrefix + userID;
			cache.remove(keyUserID);
//			cache.remove(ShiroType.flag.isLayout+userID);
		}

		// 去除sessionid对应session,就会引发重定向后session丢失的现象
//		Serializable id = session.getId();
//		if (id != null) {
//			cache.remove(session.getId().toString());
//		}
	}

	@Override
	protected void doUpdate(Session session) {
		// TODO Auto-generated method stub
		if (session instanceof ValidatingSession
				&& !((ValidatingSession) session).isValid()) {
			return; // 如果会话过期/停止 没必要再更新了
		}
		updateSession(session.getId(), session);
	}

	protected Session addSession(Serializable id, Session session) {
		if (id == null) {
			throw new NullPointerException("id argument cannot be null.");
		}

		// cache.add(session.getId().toString(), session,
		// DateUtil.getIntervalTime(30));
		cache.add(session.getId().toString(),
				SerializableUtils.serialize(session),
				DateUtil.getIntervalTime(30));
		return session;
	}

	protected Session updateSession(Serializable id, Session session) {

		if (id == null) {
			throw new NullPointerException("id argument cannot be null.");
		}
		cache.set(session.getId().toString(),
				SerializableUtils.serialize(session),
				DateUtil.getIntervalTime(30));
		// cache.set(session.getId().toString(), session,
		// DateUtil.getIntervalTime(30));
		return session;
	}
}




  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值