原谅我使用如此晦涩的词语来表达我的意思,其实我想表达的意思的用java实现类似于当其他人登录你的QQ时,你会收到“你的账号已在其他地方登录,请重新登录。”这样的东西,简单的说就是同一时刻一账号只允许一个人登录在线状态。也许就是保证时间、空间上的唯一性。但是我想强调的是这种效果绝不是单点登录,真正的单点登录是类似于Google中,使用多个产品只需要登录一次,其实QQ也有这样的功能。好了,废话少说下面说正经的。
我们最常用的用来验证用户使用登录的东西是Session,但是session并不能达到我们想要的效果,因为每个客户端访问网站的时候都会获得一个session,因此虽然是同一个账号登录系统,只要用户使用的浏览器,服务器都会产生两个session。但是每个客户端访问服务器的服务器的时候都会产生一个SessionId,而这个ID这是唯一的,我们会在后面用到。这里我们使用使用Application 域,在Java EE里面是ServletContext。这个东西是一个全局变量,当Web 程序运行的时候便会一直存在。而且整个程序只有一个Application.
于是我们可以这样。我们将数据存入Application中。而存入的内容则是:键(key)为当前用户使用用户名或者其他一个可以识别用户身份信息的ID,而值(value)则是用户得到的sessionID。这样便保证了一个账号同时至于一个用户对应。在用户登录的时候想Application中写入 key:value信息,在以后用户每次请求数据的时候,进行验证。看Application中的SessionID与用户本身的SessionID是否一致,不一致则说明多人登录。
下面是代码了:(我感觉说了好多废话)
首先获取Application:
HttpSession session = request.getSession(); //request为HttpServletRequest对象 ServletContext application = session.getServletContext();
向其中存入我们的验证数据,这里键为用户ID,值为该用户实例获得的sessionID
application.setAttribute(userId, session.getId());//userID为用户ID,
在每次验证的时候,在java里面我们可以采用至少两种方法,一种是Filter(Servlet 过滤器)、另外一种则是Spring AOC 面向切面编程,这里由于我对Spring AOC还不太熟悉,所以就用Filter,Filter具体设置,编写都不说了,只说一些怎么处理。拿到一个客户端来的请求,就进行sessionID比较,如果相同就让请求继续,如果不相同,就将该请求所对于的session清空(如果采用session验证用户是否登录,就可以达到让该用户退出登录),并给出提示信息,跳转到登录页面。
//获取application对象 ServletContext application = session.getServletContext(); String sessionId = (String) application.getAttribute(userid); String trueSessionId = session.getId(); System.out.println("sessionID====="+sessionId+"现在的sessionID"+trueSessionId); if(sessionId.equals(trueSessionId)){ //do nothing }else{ //说明有多个用户登录,去掉其session session.removeAttribute(sessionKey); //response.sendRedirect(request.getContextPath() + redirectURL); response.setContentType("text/html;charset=utf-8"); PrintWriter out = response.getWriter(); out.println(MyTools.getAlertMessage(request.getContextPath(), "您的账户已在别处登录,请重新登录", 3)); return; }
这里可以使用sendRedirect,将用户直接跳转到某个页面,但是这样不太友好,因为没有提示信息,我选择另外一个使用response给用户一些提示信息,然后设置一段时间后跳转到另外的页面。这就是我写的一个静态方法 getAlertMessage,下面贴出具体代码吧。
/** * 生成用户返回的警告页面信息 * * @param path * 系统根目录 * @param content * 需要显示的内容 * @param second * 需要停留消息的秒数 * @return String */ public static String getAlertMessage(String path, String content, int second) { StringBuilder sb = new StringBuilder(); sb.append("<html>"); sb.append("<head>"); sb.append("<meta http-equiv='refresh' content='3;url=" + path + "/login.html'>"); sb.append("<link rel='stylesheet' type='text/css' href='" + path + "/css/login.css'>"); sb.append("</head>"); sb.append("<body><form id='login'><fieldset id='inputs' style='font-size:18px;'>" + content + "," + second + "秒后你将跳转到登录页面</form></fieldset></body>"); sb.append("</html>"); return sb.toString(); }
好了,现在差不多实现这个功能的主要代码都有了。原谅我的表达能力不够好,如果各位有什么问题,留言吧。我们可以讨论一下。