mirror of
https://github.com/wahyd4/wahyd4.github.com.git
synced 2026-08-10 05:47:00 +10:00
- 308 posts reverse-extracted from wahyd4.github.com (Hexo 6.3.0 + NexT 8.25) - Hexo project with NexT theme, reading-experience custom styles - publish-post.sh: write post -> hexo build -> PR (master untouched)
83 lines
4.9 KiB
Markdown
83 lines
4.9 KiB
Markdown
---
|
||
title: "Java实现单一账号某时刻单一登录"
|
||
date: 2011-12-21 00:00:00
|
||
tags: [java, Application, JAVA EE, Session]
|
||
---
|
||
|
||
原谅我使用如此晦涩的词语来表达我的意思,其实我想表达的意思的用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:
|
||
|
||
```java
|
||
HttpSession session = request.getSession(); //request为HttpServletRequest对象
|
||
ServletContext application = session.getServletContext();
|
||
```
|
||
|
||
向其中存入我们的验证数据,这里键为用户ID,值为该用户实例获得的sessionID
|
||
|
||
```java
|
||
application.setAttribute(userId, session.getId());//userID为用户ID,
|
||
```
|
||
|
||
在每次验证的时候,在java里面我们可以采用至少两种方法,一种是Filter(Servlet 过滤器)、另外一种则是Spring AOC 面向切面编程,这里由于我对Spring AOC还不太熟悉,所以就用Filter,Filter具体设置,编写都不说了,只说一些怎么处理。拿到一个客户端来的请求,就进行sessionID比较,如果相同就让请求继续,如果不相同,就将该请求所对于的session清空(如果采用session验证用户是否登录,就可以达到让该用户退出登录),并给出提示信息,跳转到登录页面。
|
||
|
||
```java
|
||
//获取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,下面贴出具体代码吧。
|
||
|
||
```java
|
||
/**
|
||
* 生成用户返回的警告页面信息
|
||
*
|
||
* @param path
|
||
* 系统根目录
|
||
* @param content
|
||
* 需要显示的内容
|
||
* @param second
|
||
* 需要停留消息的秒数
|
||
* @return String
|
||
*/
|
||
public static String getAlertMessage(String path, String content, int second) {
|
||
StringBuilder sb = new StringBuilder();
|
||
sb.append("");
|
||
sb.append("");
|
||
sb.append("");
|
||
sb.append("");
|
||
sb.append("");
|
||
sb.append(""
|
||
+ content
|
||
+ ","
|
||
+ second
|
||
+ "秒后你将跳转到登录页面");
|
||
sb.append("");
|
||
|
||
return sb.toString();
|
||
|
||
}
|
||
```
|
||
|
||
好了,现在差不多实现这个功能的主要代码都有了。原谅我的表达能力不够好,如果各位有什么问题,留言吧。我们可以讨论一下。
|