Java 禁止同时登录,强制上一个用户下线

版权声明:转载原创文章请以超链接形式请注明原文章出处,尊重作者,尊重原创!


恰饭广告




实现效果:A用户在Google浏览器登录,B用户在Firefox浏览器登录,A用户在触发页面加载和点击事件后会被强制下线

登录页面login.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>

<title>My JSP 'login.jsp' starting page</title>

<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<script type="text/javascript"
	src="https://www.idaobin.com/js/jquery-3.2.1.js"></script>
</head>

<body>
	This is Login JSP page.
	<br>
	<input type="text" id="username" placeholder="用户名">
	<input type="text" id="pwd" placeholder="密码">
	<input type="button" id="btn" value="登录">
</body>
<script type="text/javascript">
	$(document).ready(function() {
		$("#btn").click(function() {
			var name=$("#username").val();
			var pwd=$("#pwd").val();
			$.ajax({
				type : 'Post',
				url : '/testweb/SSOLogin', //请求地址
				data : {
					name:name,
					pwd:pwd,
					action:"login"
				},
				dataType : 'text', //返回类型

				success : function(data) { //请求成功
					alert(data);
					if(data=="登录成功"){
						window.location.href="index.html";
					}
				},
				error : function(XMLHttpRequest, textStatus) { //请求失败
					if (textStatus == 'timeout') {
						var xmlhttp = window.XMLHttpRequest ? new window.XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHttp");
						xmlhttp.abort();
						alert("请求超时");
					} else if (textStatus == "error") {
						alert("服务器内部错误");
					} else if (textStatus == "parsererror") {
						alert("返回类型错误");
					}
				}
			});
		});
	});
</script>
</html>

登录servlet SSOLogin.java

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

/**
 * Servlet implementation class SSOLogin
 */
@WebServlet("/SSOLogin")
public class SSOLogin extends HttpServlet implements HttpSessionListener{


	private static final long serialVersionUID = 1L;

	/**
	 * @see HttpServlet#HttpServlet()
	 */
	public SSOLogin() {
		super();
		// TODO Auto-generated constructor stub
	}

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// TODO Auto-generated method stub
		response.getWriter().append("Served at: ").append(request.getContextPath());
	}
	
	public static final Map<String, HttpSession> USER_SESSION = new HashMap<String, HttpSession>();
	public static final Map<String, String> SESSIONID_USER = new HashMap<String, String>();
	static boolean loginstate=false;

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// TODO Auto-generated method stub
		// doGet(request, response);
		String action = request.getParameter("action");
		if (action.equals("login")) {
			userLogin(request, response);
		}
	}

	private void userLogin(HttpServletRequest request, HttpServletResponse response) throws IOException {
		String name = request.getParameter("name");
		String pwd = request.getParameter("pwd");
		if (name.equals("daobin") && pwd.equals("123456") ) {
			service(request);
			response.getWriter().print("登录成功");
		} else {
			response.getWriter().print("登录失败");
		}

	}
	
	private void service(HttpServletRequest request) throws IOException{  
        //处理用户登录(保持同一时间同一账号只能在一处登录)  
         userLoginHandle(request);
       //当前登录的用户  
 	    String name=request.getParameter("name");  
 	    HttpSession session=request.getSession();  
         //添加用户与HttpSession的绑定  
         USER_SESSION.put(name, session);  
         //添加sessionId和用户的绑定  
         SESSIONID_USER.put(session.getId(), name); 
         session.setAttribute("name", name); 
         session.removeAttribute("loginstate");
	}  

	private static void userLoginHandle(HttpServletRequest request) throws IOException{  
	    //当前登录的用户  
	    String name=request.getParameter("name");  
	    //当前sessionId  
	    String sessionId=request.getSession().getId();  
	    //删除当前sessionId绑定的用户,用户--HttpSession  
	    USER_SESSION.remove(SESSIONID_USER.remove(sessionId));  
	      
	    //删除当前登录用户绑定的HttpSession  
	    HttpSession session=USER_SESSION.remove(name);  
	    if(session!=null){  
	        SESSIONID_USER.remove(session.getId());  
	        session.removeAttribute("name");
	        session.setAttribute("loginstate", "logout"); 
	    }   
	} 

	@Override
	public void sessionCreated(HttpSessionEvent se) {
		// TODO Auto-generated method stub
		String sessionId = se.getSession().getId();
		System.out.println(sessionId);
	}

	@Override
	public void sessionDestroyed(HttpSessionEvent se) {
		// TODO Auto-generated method stub
		String sessionId = se.getSession().getId();
		// 当前session销毁时删除当前session绑定的用户信息
		// 同时删除当前session绑定用户的HttpSession
		USER_SESSION.remove(SESSIONID_USER.remove(sessionId));
	}
}

登录成功后的index.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>

<head>

<title>My JSP 'index.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<script type="text/javascript"
	src="https://www.idaobin.com/js/jquery-3.2.1.js"></script>
</head>

<body>
	<div id="btn">click</div>
	This is my Teacher page.
	<br>
</body>
<script type="text/javascript">
	function check() {
		$.ajax({
			type : 'Post',
			url : '/testweb/test', //请求地址
			data : {
				action : "check"
			},
			dataType : 'text', //返回类型

			success : function(data) { //请求成功
				if (data != "logined") {
					alert("您的账号在别处登录,您已被强迫下线");
					window.location.href = "login.html";
				}
			},
			error : function(XMLHttpRequest, textStatus) { //请求失败
				alert("会话错误,请重新登录");
				window.location.href = "login.html";
			}
		});
	}
	$(document).ready(function() {
		check();
		$("html").click(function() {
			check();
		});
	});
</script>
</html>

验证当前登录状态的servlet checklogin.java

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

/**
 * Servlet implementation class test
 */
@WebServlet("/checklogin")
public class checklogin extends HttpServlet{
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public checklogin() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		response.getWriter().append("Served at: ").append(request.getContextPath());
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		//doGet(request, response);
		String action = request.getParameter("action");
		if(action.equals("check")) {
			HttpSession session=request.getSession(); 
			String loginstate=(String) session.getAttribute("loginstate");
			if(loginstate==null) {
				response.getWriter().write("logined");
			}
			else if(loginstate.equals("logout")) {
				response.getWriter().write("logout");
			}
		}
	}
}


Spring后台代码:(小优化)

package controller;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import bll.LoginBll;

@RestController
public class LoginControl implements HttpSessionListener{
	
	LoginBll loginBll=new LoginBll();
	
	public static final Map<String, HttpSession> USER_SESSION = new HashMap<String, HttpSession>();
	public static final Map<String, String> SESSIONID_USER = new HashMap<String, String>();
	boolean sessionTimeout;
	
	
    @RequestMapping("/login.do")  
    public String login(String id,String pwd,HttpServletRequest request) {  
		Object ob=loginBll.getLogin(id, pwd);
		if(ob.equals("failed")) {
			return "failed";
		}
		else {
			HttpSession session=request.getSession();  
			session.setAttribute("user", ob); 
			service(request,id);
    		return "success";
			
		}
    }
    
    private void service(HttpServletRequest request,String id) {  
        //处理用户登录(保持同一时间同一账号只能在一处登录)  
         userLoginHandle(request,id);
       //当前登录的用户  
 	    
 	    HttpSession session=request.getSession();  
         //添加用户与HttpSession的绑定  
         USER_SESSION.put(id, session);  
         //添加sessionId和用户的绑定  
         SESSIONID_USER.put(session.getId(), id); 
         session.setAttribute("id", id); 
	}  

    private void userLoginHandle(HttpServletRequest request,String id) {  
	    //当前登录的用户  

	    //当前sessionId  
	    String sessionId=request.getSession().getId();  
	    //删除当前sessionId绑定的用户,用户--HttpSession  
	    USER_SESSION.remove(SESSIONID_USER.remove(sessionId));  
	      
	    //删除当前登录用户绑定的HttpSession  
	    HttpSession session=USER_SESSION.remove(id);  
	    if(session!=null){  
	        SESSIONID_USER.remove(session.getId());  
	        session.removeAttribute("id");
	    }
	}
    
	@Override
	public void sessionCreated(HttpSessionEvent se) {
		// TODO Auto-generated method stub
		sessionTimeout=false;
		String sessionId = se.getSession().getId();
		System.out.println(sessionId);
	}
    
    @Override
	public void sessionDestroyed(HttpSessionEvent se) {
		// TODO Auto-generated method stub
		String sessionId = se.getSession().getId();
		// 当前session销毁时删除当前session绑定的用户信息
		// 同时删除当前session绑定用户的HttpSession
		sessionTimeout=true;
		USER_SESSION.remove(SESSIONID_USER.remove(sessionId));
	}
    
    @RequestMapping("/checkLogin.do")  
    public String checkLogin(String action,HttpServletRequest request) {
    	if(action.equals("check")) {
    		if(!sessionTimeout) {
    			String sessionId=request.getSession().getId();  
        		String user=SESSIONID_USER.get(sessionId);
        		if(user==null) {
        			return "logout";
        		}
        		else {
        			return "logined";
        		}
    		}
    		return "timeout";
    	}
    	return "error";
    }
}

js:

function check() {
    $.ajax({
        type: 'Post',
        url: '/checkLogin.do', //请求地址
        data: {
            action: "check"
        },
        dataType: 'text', //返回类型

        success: function (data) { //请求成功
        	console.log(data);
            if (data == "logout") {
                alert("您的账号在别处登录,您已被强迫下线,请注意保管密码");
                window.location.href = "login.html";
            }
            if(data == "timeout"){
            	 alert("会话超时,请重新登录");
                 window.location.href = "login.html";
            }
            if (data == "error") {
                alert("会话错误,请重新登录");
                window.location.href = "login.html";
            }

        },
        error: function (XMLHttpRequest, textStatus) { //请求失败
            alert("会话错误,请重新登录");
            window.location.href = "login.html";
        }
    });
}
$(document).ready(function () {
    check();
    $("html").click(function () {
        check();
    });
});

注意:每秒定时请求会造成服务器和网络传输压力 定时触发改为点击html事件触发和页面加载事件

原文链接:https://www.idaobin.com/archives/2079.html

让我恰个饭吧.ヘ( ̄ω ̄ヘ)

支付宝 ——————- 微信
图片加载中图片加载中



恰饭广告

发表评论

电子邮件地址不会被公开。 必填项已用*标注

1 × 6 =