异地登录

前提:系统做了拦截器,每个用户使用时,必须先登录

配置文件

<filter>
    <filter-name>permissionFilter</filter-name>
    <filter-class>com.ccf.commons.filter.PermissionFilter</filter-class>
    <init-param>
        <param-name>ignore_page</param-name>
        <param-value>/user/login.do, /user/logout.do</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>permissionFilter</filter-name>
    <url-pattern>*.jsp</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>permissionFilter</filter-name>
    <url-pattern>*.do</url-pattern>
</filter-mapping>


<listener>
	<listener-class>com.ccf.commons.listener.SessionListener</listener-class>
</listener>

step1:登录操作:

1、根据isLogout参数的值来判断登录界面是否需要提醒用户:您的账号在其他IP登录,已被踢下线

2、缓存用户名和对应的sessionID,并在session中添加isLogout属性

/**
 * 登录
 * @param request
 * @param session
 * @param sysUser
 * @return
 * @throws IOException 
 */
@RequestMapping("/login")
public ModelAndView login(HttpServletRequest request,HttpServletResponse response, HttpSession session, User sysUser, String isLogout) throws IOException{
	ModelAndView modelAndView = new ModelAndView("/login");
	if("true".equals(isLogout)){
		modelAndView.addObject("user_error", "您的账号在其他IP登录,已被踢下线");
		return modelAndView;
	}
	
	//异地登陆
	Map<String, HttpSession> sessionMap  = CacheManager.getSessionMap();
	if(false == sessionMap.containsKey(loginId)){
		session.setAttribute("isLogout", "false");
		
		sessionMap.put(loginId, session);
		CacheManager.setSessionMap(sessionMap);
	}else if(session.getId() != sessionMap.get(loginId).getId()){
		HttpSession sessionDel = sessionMap.get(loginId);
		sessionDel.setAttribute("isLogout", "true");
		
		session.setAttribute("isLogout", "false");
		sessionMap.put(loginId, session);		//更新loginId
		CacheManager.setSessionMap(sessionMap);
	}
	
	return new ModelAndView("redirect:/index.jsp");
}

 step2:前端

index.js

定时判断session的属性isLogout的值,如果为 'true',说明有其他用户在其他地方登录了,所以调用退出,并带isLogout参数

$(function() {
	//异地登录
	var logoutInterval = setInterval(function(){
		$.ajax({
			url : rootPath+"/user/checkSession.do",
			type:"post",
			success : function(data) {
				if(data == "true"){
					window.location.href = rootPath + "/user/logout.do?isLogout=true";
				}
			}
		});
	},15 *1000);
});

其中,判断方法如下:

/**
 * 用户是否已异地登录
 * @param userId
 * @return
 */
@RequestMapping("/checkSession")
@ResponseBody
public String checkSession(HttpServletRequest request, HttpSession session){
	return (String) session.getAttribute("isLogout");
}

step3:退出操作

1、删除整个会话(session)

2、重定向到登录操作

/**
* 退出系统
 * @return
 */
@RequestMapping(value = "logout")
public void loginOut(HttpSession session,HttpServletRequest request,HttpServletResponse resp, String isLogout) {
    session.invalidate();
	String resultUrl=request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+request.getContextPath()+"/user/login.do?isLogout="+isLogout;
	try {
		resp.sendRedirect(resultUrl);
	} catch (IOException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
}

step4:过滤器拦截

public class PermissionFilter implements Filter {
	
	private String[] ignorePages;
	
	public void init(FilterConfig config) throws ServletException {
		String ignorePage = config.getInitParameter("ignore_page");
		if (ignorePage != null)
		      this.ignorePages = ignorePage.split(",");
	}

	public void doFilter(ServletRequest req, ServletResponse resp,
			FilterChain chain) throws IOException, ServletException {
		HttpServletRequest request = (HttpServletRequest)req;
		HttpServletResponse response = (HttpServletResponse)resp;
		HttpSession session = request.getSession();
		
		User user = (User)session.getAttribute(Constants.USER_INFO);
		String interurl = request.getContextPath() + request.getServletPath();
		
		// 判断用户访问的是否是登录页面
		if (isIgnorePage(request)) {
			SessionUtil.setUser(user);
			chain.doFilter(request, response);
			return;
		}
		
		// 校验是否验证会话
		if (null == user){//判断是否已登录
			if (isIgnorePage(request)){
				SessionUtil.setUser(user);
				chain.doFilter(req, resp);
				return;
			}
			response.sendRedirect(request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+request.getContextPath()+"/user/login.do");
		}else{
			if (interurl.equals("/{系统名}/login.jsp")) {
				response.sendRedirect(request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+request.getContextPath()+"/index.jsp");
			} else {
				SessionUtil.setUser(user);
				chain.doFilter(request, response);
			}
		}
	}

	private boolean isIgnorePage(HttpServletRequest request) {
		if (this.ignorePages == null) {
			return false;
		}
		
		String servletPath = request.getServletPath();
	    for (int i = 0; i < this.ignorePages.length; i++) {
	    	if (this.ignorePages[i].endsWith("*")) {
	    		int lastIndex = servletPath.lastIndexOf("/");
    			String compareUrl = null;
    			if (lastIndex == 0)
					compareUrl = "/*";
    			else {
					compareUrl = servletPath.substring(0, lastIndex) + "/*";
    			}
    			if (this.ignorePages[i].endsWith(compareUrl)) {
    				return true;
    			}
	    	} else if (this.ignorePages[i].equals(servletPath)) {
	    		return true;
	    	}
	    }
	    return false;
	}

	public void destroy() {
	}

}

step5:登录界面

login.jsp

${user_error}:el表达式,它会从page,request,session,application中取值

<html>
    <head>
	<div style="margin: 20px 0 0 0;padding: 0;text-align: center;">
	    <span style="font-size: 16px;color: #E70102;">${user_error}</span>
	</div>
    </body>
</html>

为了避免用户没有调用退出操作(logout),当session结束(session过期、用户直接退出浏览器等),做以下补充

提供一个session的监听器,确保Cache类能正常使用

public class SessionListener implements HttpSessionListener {

	@Override
	public void sessionCreated(HttpSessionEvent se) {
		// TODO Auto-generated method stub
	}

	@Override
	public void sessionDestroyed(HttpSessionEvent se) {
		// TODO Auto-generated method stub
		HttpSession session = se.getSession();
		
		Map<String, HttpSession> sessionMap  = CacheManager.getSessionMap();
		Collection<HttpSession> col = sessionMap.values();
		
		while(true == col.contains(session)){
			col.remove(session);
		}
	}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值