JavaWeb-实现多ip、异地 同时登录踢人下线

java异地登录验证_同一帐号异地登录 在此之前也看了很多同一帐号异地登录的,有的是采用后登录者必须等待前登录者释放后才可以登录,我的项目中要用到想qq那样可以踢出,我具体的做法如下:LoginServelt.java 做登录使用OnlineUserListener.java 做session超时清理工作LogValidata.java 做权限验证logout.jsp做退出LoginServelt.java public void se... 阅读详情

点击上方蓝色字体,选择“标星公众号”

优质文章,第一时间送达

  • 所用知识点罗列:

cookie 、session、serverlet过滤器、serverlet监听器,前提环境是基于Session实现的登录功能
(Session中存放了登录者的ip,userName等信息作已登录标记)
  • 需要理解的基本概念

Session是基于cookie的,请求会话中,通过浏览器cookie携带的JsessionId
的sessionId号来找到服务器中相应的Session的.
如果没有设置cookie的有效时间,一旦浏览器关闭,cookie就消失了,
其携带的sessionId也就丢失了,
这时即使服务器中的当前用户的Session还未过期失效,依然存在,也无法找到了,基本等于是销毁了.
  • 问题关键所在

正常使用Session实现的登录时把登陆标记存放在Session中,在一次会话中有效。
Session是以会话为隔离的,(其他浏览器或其他电脑也可以在打开一个会话),不同会话就可以创建同一用户的不同session。
也就造成了服务器端可以有任意多个SessionId不同,但Session内容却相同的Session,
也即是同一个用户可以在多个浏览器登录,无论是否是在同一台电脑(ip)、同一个地区。
这也是我们要实现多ip登录踢人下线功能要解决的问题。
  • 解决方案思路

1. 自己实现MySessionContext类搞一个map静态成员变量以<SessionId,Session>的方式装所有的Session,放服务器的运行内存中待用.
(其实使用serverletContext作为容器也可以替代Session和这个自己实现的SessionContext)

2. 搞一个Session监听器,监听Session的创建和销毁,在新的session创建时将其加入到上面自己创建的
MySessionContext的静态成员变量map中,Session销毁时(或者用户注销登录时)把他的Session移除出map,
并用Session.invalidate()销毁.

3. 用一个过滤器拦截过滤登录请求,获取登录用户的登录标记,然后遍历装有Session的map,
对照是否有当前登录用户的Session存在,如果没有就放行通过;
如果有,取出找到的session(也即是前一个登录者生成的Session)移除出MySessionContext的map容器,
并销毁这个Session(调用invalid()方法).此时前一个登录者再刷新页面时发现Session已经不存在了,配合先前做的Session过期过滤处理,就会和Session过期有一样的效果——下线.

  • 参考代码

登录操作:

//获取登录ip地址
String ip = request.getRemoteAddr();
//将登录者的ip放入到session中
request.getSession().setAttribute(ESessionKey.LoginIP.key, ip);
request.getSession().setAttribute(ESessionKey.UserId.key, user.getUserId());// 将用户id存放到session中,作为已登录标记

MySessionContext实现

public class MySessionContext {
    private static HashMap<String,HttpSession> mymap = new HashMap<String,HttpSession>();
    public static synchronized void AddSession(HttpSession session) {
        if (session != null) {
            mymap.put(session.getId(), session);
        }
    }
    public static synchronized void DelSession(HttpSession session) {
        if (session != null) {
            HttpSession session2 = mymap.remove(session.getId());//移出session
            if(session2!=null){
                session2.invalidate();//将从sessionContext中移出的Session失效 --相当于清除当前Session对应的登录用户
            }
        }
    }
    public static synchronized HttpSession getSession(String session_id) {
        if (session_id == null)
            return null;
        return (HttpSession)mymap.get(session_id);
    }

    public static HashMap<String, HttpSession> getMymap() {
        return mymap;
    }
}

Session监听器

public class SessionCounter implements HttpSessionListener {   

    private static int activeSessions = 0;   

    public void sessionCreated(HttpSessionEvent se) { 
        MySessionContext.AddSession(se.getSession());
        activeSessions++; 
        System.out.println("++++++++玩家上线了++++++++");
    }   

    public void sessionDestroyed(HttpSessionEvent se) {  
        if(activeSessions > 0)   
            activeSessions--;
        HttpSession session = se.getSession();
        MySessionContext.DelSession(session);
    }   

    public static int getActiveSessions() {   
        return activeSessions;   
    }   
}   

踢人下线过滤器核心代码

public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request =  (HttpServletRequest)req;
        HttpServletResponse response =  (HttpServletResponse)resp;
        String localIp = request.getRemoteAddr();//获取本地ip
        HttpSession session = null;
        String user_id = (String)request.getParameter("userId"); //登录请求时填写的 
        if(StringUtils.isNotBlank(user_id))
        {
            session = getLoginedUserSession(user_id);
        }
        String loginedIp = null;
        if(session!=null)
        {
            loginedIp = (String)session.getAttribute(ESessionKey.LoginIP.key);//获取已登录者ip(如果有)
        }
        if(StringUtils.isNotBlank(loginedIp) && !localIp.equals(loginedIp)){
            MySessionContext.DelSession(session);//踢人--找到并销毁Session
            request.setAttribute("msg", "您的账号在其它ip登录,您被踢下线了!");
            request.getRequestDispatcher("/login.jsp").forward(request, response);
        }else{
            chain.doFilter(request, response);//放行
        }
    }

Session过期过滤器 核心代码

@Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
        System.out.println("过滤请求...");

        HttpServletRequest request =  (HttpServletRequest)req;
        HttpServletResponse response =  (HttpServletResponse)resp;
        //session中获取用户名信息  
        String userId = (String)request.getSession().getAttribute("userId");  
        String admin = (String)request.getSession().getAttribute("admin");  

        //普通用户登录过滤,如果用户名为空说明带有登录标记的Session过期了
        if (userId==null||"".equals(userId.toString()) ) { 
            //超级管理员过滤
            if(admin==null||"".equals(admin.toString())){
               response.sendRedirect(request.getContextPath()+ADMIN_URL);
               return ;
            }

            //如果普通用户和超级管理员都没有登陆内容,说明登录过期
            System.out.println("登录过期,请重新登录!");
            response.sendRedirect(request.getContextPath()+LOGIN_URL);
            PrintWriter printWriter = response.getWriter();
            String relogin = "登录过期,请重新登录!";
            printWriter.write(relogin);
            printWriter.flush();
            printWriter.close();
            return ;
        }
        //过滤通过,放行
        chain.doFilter(request, response);
        System.out.println("过滤响应!");
    }

web.xml配置

 <!-- 登录踢人过滤器 -->
  <filter>
    <filter-name>TickFronterFilter</filter-name>
    <filter-class>com.fengyun.web.filter.TickFronterFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>TickFronterFilter</filter-name>
    <url-pattern>/login.html</url-pattern>
  </filter-mapping>
    <!-- session监听器 -->
   <listener>
    <listener-class>   
        com.fengyun.web.filter.SessionCounter   
    </listener-class>
  </listener>
    <!-- session过期过滤器 -->
  <filter>
    <filter-name>Loginfilter</filter-name>
    <filter-class>com.fengyun.web.filter.LoginOverdueFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>Loginfilter</filter-name>
    <url-pattern>/material/*</url-pattern>
   ...等等需要过滤的url地址...当然可以使用通配方式写(此处不详述)
    <url-pattern>/operate_editeCompact.html</url-pattern>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>INCLUDE</dispatcher>
    <dispatcher>ERROR</dispatcher>
  </filter-mapping>

版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

本文链接:

https://blog.youkuaiyun.com/zlsdmx/article/details/73650990

雪亮工程视频联网技术详解:视综平台主流接入方式与协议分析 随着雪亮工程建设的深入,视频资源的汇聚与共享成为核心需求。本文简要剖析了雪亮视综平台下的视频联网接入技术,重点讲解了主流接入方式的区别与选型,并深入探讨了平台内部及跨平台的视频资源共享机制(含级联与推送模式),旨在为安防开发人员和系统集成商提供清晰的架构思路与技术参考。 阅读详情

相关推荐

GD32F450以太网(2-2): PHY芯片IP101GR介绍

IP101是台湾省九阳电子公司生产制造的,符合IEEE 802.3/802.3u标准单端口快速以太网收发器100Mbps和10Mbps操作,它支持自动MDI/MDIX功能,简化网络安装和减少系统维护成本。支持Auto MDI/MDIX已内置4个49.9欧的精密电阻支持中断功能支持 MII/RMII 接口超低功耗

Zhichao_Zhang的博客 1万+

Java防止用户同一时间重复登录(包括异地登录)

有时候我们在做登录模块过程中难免会遇到这种问题,即使我们给用户进行了多重判断,比如:用户名,管理员,验证码,一系列的判断… 你是否真正考虑到用户的体验,比如不能让用户在同一时间,同一个浏览器重复登录问题,同时也包括不同浏览器登录(异地登录)问题。 这些都是我们应该去考虑的。如果是用Spring 框架的话,Spring security 是可以实现防止用户重复登录的问题的,但我这里并没有用到框架,因...

Brave的博客 4189

卸载重装Ubuntu22.04双系统

先说一下写此篇文章的背景吧,我在Windows下配置了三个cornerNet深度学习环境分别是cuda10.3(显卡版本太高不支持),cuda11.3(配置后偶然看到一篇说这个版本win下只能用CPU跑),最后是cuda11.1终究还是没能跑通代码,因为它的代码是在Liunx系统写的,就想着装个Ubuntu试试看,在网上看说一般软件不要装太高版本,我就下载了470版的显卡驱动,跟着步骤升级了系统内核,结果第二天开机Ubuntu就崩了,开机黑屏左上角只有一道横杠显示,只能按ctrl+shift+f5进入命令窗

编程小白的博客 8116

Java 异地登陆账号怎么提示

异地登陆账号提示方案 1. 问题背景 在开发Web应用程序时,用户账号安全是一个重要的问题。如果用户在异地登陆账号,可能会涉及到账号被盗用的风险。因此,我们需要一个方案来实现Java异地登陆账号的提示功能。 2. 方案描述 我们可以通过记录用户的登录地点信息,当用户在新的地点登录时,系统会提示用户账号可能存在异常的情况。具...

weixin_40252124的博客 426

详解TCP/IP五层模型

TCP/IP模型是一个网络通信体系结构,由五层组成,每一层都有其特定的功能。应用层传输层网络层数据链路层物理层每一层都有不同的责任,通过这种层次结构,网络通信可以更有效地进行。

2201_75437633的博客 1万+

【STM32】从零构建串口IAP框架:BootLoader与App双向跳转实战解析

本文详细解析了STM32串口IAP框架的构建,重点阐述了BootLoader与App双向跳转的实战原理与实现步骤。内容涵盖Flash分区规划、中断向量表重定向、通信协议设计及固件升级流程,并针对跳转失败、程序跑飞等常见问题提供了解决方案,帮助开发者掌握产品级远程升级的核心技术。

wind6的博客 838

Java-实现异地登陆和超时登陆

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34246551的博客 2707

Unity游戏开发实战:手把手教你用C#实现一个简单的反向运动学(IK)控制器

本文详细介绍了在Unity游戏开发中如何使用C#实现一个简单的反向运动学(IK)控制器。通过建立骨骼层级结构、实现CCD算法和角度限制,开发者可以轻松创建自然的角色动画效果。文章还提供了可视化调试工具和性能优化方案,帮助提升开发效率。

weixin_42523711的博客 244

java web怎么实现踢人_JavaWeb-实现多ip、异地 同时登录踢人下线

JavaWeb-实现多ip、异地 同时登录踢人下线2017年06月23日 18:46:48阅读数:2666所用知识点罗列:cookie 、session、serverlet过滤器、serverlet监听器,前提环境是基于Session实现的登录功能(Session中存放了登录者的ip,userName等信息作已登录标记)12需要理解的基本概念Session是基于cookie的,请求回话中,通过浏览...

weixin_42499067的博客 775

抄表程序员的DLMS/COSEM协议实战:从抓包到解析,手把手教你读懂IEC62056报文

本文深入解析DLMS/COSEM协议在智能电表通信中的应用,从报文捕获到数据解析的全流程实战指南。涵盖HDLC帧解析、应用层连接建立、数据请求/响应解码等核心内容,并提供Wireshark配置、OBIS代码速查表等实用工具,帮助开发者快速掌握IEC62056标准下的电能表通信技术。

weixin_29178069的博客 302

qPCRtools | 神仙R包分分钟搞定你的qPCR实验结果!~

1写在前面 不知道大家都是怎么完成qPCR的计算的,在不会R的时候,我是用一个祖传的Excel表进行计算的。🤣 但是,一直有个缺点,如果需要计算的量比较大时,就不方便了,去搜了一下文献,发现了一个最近发表的R包,不仅可以计算反转录的RNA体积,还可以帮助选择定量方法,简直是神仙R包,本期就介绍一下它的使用吧。🥰 感谢原作者的开发,嘿嘿,文末有引用方法。👀 2用到的包 rm(list = ls())library(tidyverse)library(ggsci)library(qPCRtools)librar

m0_72224305的博客 3986

Java最全JavaWeb-实现多ip、异地 同时登录踢人下线(1),腾讯技术官发布的“神仙文档”火爆网络

/将从sessionContext中移出的Session失效 --相当于清除当前Session对应的登录用户。System.out.println(“++++++++玩家上线了++++++++”);System.out.println(“登录过期,请重新登录!

2401_84585316的博客 1064

(计算机组成原理)第二章数据的表示和运算-第二节:数字电路基础知识

本文介绍了计算机组成原理中的逻辑门电路、多路选择器和三态门。逻辑门电路包括基本逻辑运算(与、或、非)和复合逻辑运算(与非、或非、异或、同或),这些运算通过门电路实现,并满足分配律和结合律。多路选择器(MUX)用于从多个输入信号中选择一个输出,广泛应用于数据选择、资源共享和逻辑函数实现等场景。三态门则具有三种输出状态(高电平、低电平、高阻态),常用于总线控制和信号隔离。这些元件在数字电路设计和计算机系统中具有重要作用。

快乐江湖的博客 2476

java 实现异地登陆_Java实现用户异地登陆踢人操作

使用框架:Shiro+SpringBoot首先,我先说步骤:1.登陆2.查看该用户是否已经登陆 是:3 否:正常登陆3.将已登陆用户踢出,自己登陆。这只是说原理,具体实现现在说。踢出已登陆用户,主要体现在对已登陆用户session的处理上,原理简单,就是将已登陆用户的session删除就好。难点在于如何找到该用户的session。这里,我使用了redis首先,在登陆的时候获取用户的sessio...

weixin_36486395的博客 2027

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

java实现同用户登录互挤,将前一个用户挤下线

1.场景 假设 Tom使用了用户1,Joker也是使用了用户1,两人同时对用户1 的相关数据进行了修改,就会造成数据的安全隐患,得保证多台设备登录账号只有一个账号能登录上。 2.思路 2.1 利用map的key-value数据结构,key可以重复,value不能重复的特性,将用户名和sessionid绑定存储起来。 2.2 首次登录在拦截器里面放行,登录成功将用户名和sessionid存储起来,当第二次登录时,用户名相同,sessionid不同的话则去登录,后面执行登录方法,发前一个账号和sessioni

zouyang920的博客 5383

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

java强制下线 session,登录的多地挤下线功能 redis session

使用redis储存session使用redis 存储 信息 和本地session 做比较如果相同 表明是同一次登录如果和redis不同 表明不是同一次登录 强制下线即可req.headers.session 和 redis中做比较1.redis存储store.hset("investorToken",req.session.uid,req.session.investorToken, funct...

weixin_33489687的博客 842

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

java 实现登录超时,Java-实现异地登陆和超时登陆

一、原理1. 异地登陆同一个账号,在不同的电脑(也可以不同的浏览器)登陆系统,前一个已经登陆的账号session被销毁,用户进行下一步操作时跳转错误页面。2. 超时登陆登陆后无操作*分钟后自动销毁session,用户进行下一步操作时跳转错误页面。3. 区分异地登陆和超时登陆起效时跳转的错误页面不相同。二、实现1.超时登陆由系统控制,在web.xml中配置,或者由监听器控制,利用session.s...

weixin_42500156的博客 2572

java jwt登录_JWT认证登陆方式

JWT认证登陆方式在学习前后端分离的过程中往往遇到的第一个问题就是登陆验证问题,以前的我们将Cookie、Session、Token,在我的学习过程中认识了JWT验证方案,纯属自己理解,有错还望大佬指出。JWT 全称是 JSON Web Token,是目前非常流行的跨域认证解决方案.前情回顾早期的Cookie和Session的认证方式,之前没有进行前后端分离的模式大部分使用的是Cookie-Ses...

weixin_28676983的博客 1386

web项目通过Session监听器控制在线人数以及同一用户异地登陆限制

对于项目中要求控制同时在线人数的需求,可以通过Session监听器来实现。 Session监听器类: public class UserLoginListener implements HttpSessionAttributeListener { @Override public void attributeAdded(HttpSessionBindingEvent se)

wewewfs的专栏 1389

java异地登录 怎么解决_同一帐号异地登录

在此之前也看了很多同一帐号异地登录的,有的是采用后登录者必须等待前登录者释放后才可以登录,我的项目中要用到想qq那样可以踢出,我具体的做法如下:LoginServelt.java 做登录使用OnlineUserListener.java 做session超时清理工作LogValidata.java 做权限验证logout.jsp做退出LoginServelt.java public void se...

weixin_39958100的博客 965
上一篇: @Autowire和@Resource注解使用的正确姿势,别再用错的了!!
下一篇: 这款IDEA插件刷爆了朋友圈,网友:这用起来有点酸爽~
Java思维导图
博客等级 码龄10年 306粉丝 71原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值