Java Web防止用户重复登录(同一用户同时登录)的一种实现方案

1.思路

在Java web项目中,有时需要防止用户重复登录,解决方案有多种。比如Spring security就可以防止用户重复登录。 这里给出一个简单的解决方案:在处理登录的login方法中,先查询数据库验证下该用户是否存在,如果存在 判断该登录账户是否已经锁定了, 然后从application内置作用域对象中取出所有的登录信息,查看该username账户是否已经登录,如果登录了,就友好提示下,反之表示可以登录,将该登录信息以键值对的方式保存在application中。 当用户注销时,删除application中相关数据即可。

2.示例代码

2.1 处理登录方法

    @RequestMapping("/checkLogin.do")
    public String checkLogin(HttpSession session, String username, String password) {
        System.out.println("checkLogin.do");

        UserBean user=userService.login(username,password);
        if(user!=null){//登录成功

            //session.getServletContext()得到时application对象
            ServletContext application=session.getServletContext();
            Map<String, String> loginMap = (Map<String, String>)application.getAttribute("loginMap");
            if(loginMap==null){
                loginMap = new HashMap<>();
            }
            for(String key:loginMap.keySet()) {
                if (user.getUsername().equals(key)) {
                    if(session.getId().equals(loginMap.get(key))) {
                        System.out.println(username+"在同一地点多次登录!");
                    }else{
                        System.out.println(username+"异地登录被拒绝!");
                        session.setAttribute("tip", "该用户已经异地登录!");
                        return "forward:/index.jsp";
                    }
                }
            }
            loginMap.put(user.getUsername(),session.getId());
            application.setAttribute("loginMap", loginMap);
            session.setAttribute("username",user.getUsername());
            System.out.println("登录成功!");
            return "redirect:/index";
        }else{
            //登录失败
            System.out.println("登录失败!");
            session.setAttribute("tip","登录失败!");
            return "forward:/index.jsp";
        }
    }

2.2 销毁Session

package cn.hadron.servlet;

import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import java.util.Map;

/**
 * Created by root on 17-9-28.
 */
public class SessionListener implements HttpSessionListener {

    @Override
    public void sessionCreated(HttpSessionEvent event) {

    }

    @Override
    public void sessionDestroyed(HttpSessionEvent event) {
        //在session销毁的时候 把loginMap中保存的键值对清除
        String username = event.getSession().getAttribute("username").toString();
        if(username!=null){
            Map<String, String> loginMap = (Map<String, String>)event.getSession().getServletContext().getAttribute("loginMap");
            loginMap.remove(username);
            event.getSession().getServletContext().setAttribute("loginMap",loginMap);
            System.out.println(username+"用户注销!");
        }
    }

}

2.3 web.xml

  <listener>
    <listener-class>cn.hadron.servlet.SessionListener</listener-class>
  </listener>

2.4 登录页面

${tip}
<form action="/user/checkLogin.do" method="post">
    帐号:<input type="text" name="username"><br>
    口令:<input type="password" name="password"><br>
    <input type="submit" value="登录">
</form>

3 测试

3.1 本地登录

注意:本地可以多次登录。

3.2 异地登录

另找一台机器测试

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏JadePeng的技术博客

Angular快速学习笔记(4) -- Observable与RxJS

4332
来自专栏Android先生

Android开发者怎么能不会写后台接口呢?

然后在src下创建三个包,一个放Servlet,一个放mysql的工具类,一个放对象;

632
来自专栏闻道于事

JavaWeb(六)Listener监听器

监听器 监听器就是一个实现特定接口的普通java程序,这个程序专门用于监听另一个java对象的方法调用或属性改变,当被监听对象发生上述事件后,监听器某个方法将立...

6525
来自专栏程序猿DD

基于Consul的分布式锁实现

我们在构建分布式系统的时候,经常需要控制对共享资源的互斥访问。这个时候我们就涉及到分布式锁(也称为全局锁)的实现,基于目前的各种工具,我们已经有了大量的实现方式...

2825
来自专栏腾讯云Elasticsearch Service

Elasitcsearch 底层系列 Lucene 内核解析之 Stored Fields

Lucene 的 stored fields 主要用于行存文档需要保存的字段内容,每个文档的所有 stored fields 保存在一起,在查询请求需要返回字段...

1101
来自专栏MasiMaro 的技术博文

IRP的同步

以WriteFile为例,一般的同步操作是调用WriteFile完成后,并不会返回,应用程序会在此处暂停,一直等到函数将数据写入文件中并正常返回,而异步操作则是...

1484
来自专栏扎心了老铁

django中间件Middleware

熟悉web开发的同学对hook钩子肯定不陌生,通过钩子可以方便的实现一些触发和回调,并且做一些过滤和拦截。 django中的中间件(middleware)就是类...

3807
来自专栏大内老A

[ASP.NET MVC] 利用自定义的AuthenticationFilter实现Basic认证

很多情况下目标Action方法都要求在一个安全上下文中被执行,这里所谓的安全上下文主要指的是当前请求者是一个经过授权的用户。授权的本质就是让用户在他许可的权限范...

23310
来自专栏Java 技术分享

Session、Cookie 学习笔记

3725
来自专栏Java面试笔试题

MyBatis <set>标签的使用

MyBatis在生成update语句时若使用if标签,如果前面的if没有执行,则可能导致有多余逗号的错误。 使用set标签可以将动态的配置SET 关键字,和剔...

812

扫码关注云+社区