# Java实现单一账号某时刻单一登录 | 大染志
原谅我使用如此晦涩的词语来表达我的意思，其实我想表达的意思的用java实现类似于当其他人登录你的QQ时，你会收到“你的账号已在其他地方登录，请重新登录。”这样的东西，简单的说就是同一时刻一账号只允许一个人登录在线状态。也许就是保证时间、空间上的唯一性。但是我想强调的是这种效果绝不是单点登录，真正的单点登录是类似于Google中，使用多个产品只需要登录一次，其实QQ也有这样的功能。好了，废话少说下面

大染志

Junv's blog

# Java实现单一账号某时刻单一登录

发表于 2011-12-21 更新于 2026-08-04

原谅我使用如此晦涩的词语来表达我的意思，其实我想表达的意思的用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:

    1
    2

    HttpSession session = request.getSession(); //request为HttpServletRequest对象
        ServletContext  application = session.getServletContext();

向其中存入我们的验证数据，这里键为用户ID，值为该用户实例获得的sessionID

    1

    application.setAttribute(userId, session.getId());//userID为用户ID，

在每次验证的时候，在java里面我们可以采用至少两种方法，一种是Filter(Servlet 过滤器)、另外一种则是Spring AOC 面向切面编程，这里由于我对Spring AOC还不太熟悉，所以就用Filter，Filter具体设置，编写都不说了，只说一些怎么处理。拿到一个客户端来的请求，就进行sessionID比较，如果相同就让请求继续，如果不相同，就将该请求所对于的session清空（如果采用session验证用户是否登录，就可以达到让该用户退出登录）,并给出提示信息，跳转到登录页面。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16

    //获取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,下面贴出具体代码吧。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28

    /**
         * 生成用户返回的警告页面信息
         *
         * @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();

        }

好了，现在差不多实现这个功能的主要代码都有了。原谅我的表达能力不够好，如果各位有什么问题，留言吧。我们可以讨论一下。

0%