java web 限制同一个用户在不同处登入
用到的技术:map集合,sessionListener监听器,Fiter过滤器。
实现思路:
一.利用一个全局的map集合来保存每个用户sessionID的值的一个集合。一个用户对应一个sessionID当相同的用户登录的时候判断它在集合总有没有值。(保存用户所有登录记录)
二.
2.1.实现sessionListener在当一个session被销毁的时候强制移除当前用户所对应的sessionID
2.2.实现Fiter来判断每次请求map集合中是否有值。(实现强制退出)
代码:代码是复制别人的,做了些修改。
public class LoginUserMap {ConcurrentHashMap这个集合是线程安全的而且性能方面比hasTable和hasMap都好。在高并发的条件下执行速度更快。 private static Map<String, String> loginUsers = new ConcurrentHashMap<String, String>(); /** * 将用户和sessionId存入map * @param key * @param value */ public static void setLoginUsers(String loginId, String sessionId) { loginUsers.put(loginId, sessionId); } /** * 获取loginUsers * @return */ public static Map<String, String> getLoginUsers() { return loginUsers; } /** * 根据sessionId移除map中的值 * @param sessionId */ public static void removeUser(String sessionId) { for (Map.Entry<String, String> entry : loginUsers.entrySet()) { if (sessionId.equals(entry.getValue())) { loginUsers.remove(entry.getKey()); break; } } } /** * 判断用户是否在loginusers中 * @param loginId * @param sessionId * @return */ public static boolean isInLoginUsers(String loginId, String sessionId) { return (loginUsers.containsKey(loginId) && sessionId.equals(loginUsers.get(loginId))); }}//登录方法所在的地方public void login(ttpServletRequest request) { try { ......//一系列登录的方法 HttpSession session = request.getSession(); LoginUserMap.setLoginUsers(username, session.getId());//保存sessionId到map中 } catch (LoginException ex) { throw ex; }}HttpSessionListener public class SessionListener implements HttpSessionListener { private Log log = LogFactory.getLog(SessionListener.class); /** * 创建session时候的动作 * @param event */ @Override public void sessionCreated(HttpSessionEvent event) { } /** * 销毁session时候的动作 * @param event */ @Override public void sessionDestroyed(HttpSessionEvent event) { HttpSession session = event.getSession(); String sessionId = session.getId(); //移除loginUsers中已经被销毁的session LoginUserMap.removeUser(sessionId); log.info(sessionId + "被销毁!"); }}<listener> <listener-class>....SessionListener</listener-class></listener>public class LoginLimitFilter implements Filter{ private Log log = LogFactory.getLog(LoginLimitFilter.class); /** * 销毁时的方法 */ @Override public void destroy() { } /** * 过滤请求 * @param request * @param response * @param filterChain * @throws IOException * @throws ServletException */ @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest servletRequest = (HttpServletRequest) request; HttpServletResponse servletResponse = (HttpServletResponse) response; HttpSession session = servletRequest.getSession(); //获取项目路径 String path = servletRequest.getContextPath(); String basePath = servletRequest.getScheme()+"://"+servletRequest.getServerName()+":"+servletRequest.getServerPort()+path; try { //获取登录信息 String loginId = session.getAttribute("yhid") //判断当前用户的sessionId是否在loginUsers中,如果没有执行if后的操作 if(!LoginUserMap.isInLoginUsers(loginId, session.getId())) { //当前用户logout 注:退出登录最好别用session销毁的方法。 logout();//自己的logout方法 //调到登录页面,并表明退出方式为挤下线 servletResponse.sendRedirect(basePath + "?logoutway=edge"); } } catch (Exception e) { log.debug("获取当前用户信息失败,用户未登陆!", e); } finally { filterChain.doFilter(request, response); } } /** * 初始化方法 * @param arg0 * @throws ServletException */ @Override public void init(FilterConfig arg0) throws ServletException { }}<filter> <filter-name>LoginLimitFilter</filter-name> <filter-class>io.github.brightloong.loginlimite.LoginLimitFilter</filter-class></filter><filter-mapping> <filter-name>LoginLimitFilter</filter-name> <url-pattern>/*</url-pattern></filter-mapping>window.onload = function(){ if(window.parent != window){ window.parent.location.href=window.location.href; } else { if(GetQueryString('logoutway')) { alert('该用户已在其他地方登录,你已下线'); var url = window.location.href; window.location.href = url.substr(0,url.indexOf('?logoutway=edge')); } }}function GetQueryString(name){ var reg = new RegExp("(^|&)"+ name +"=([^&]*)(&|$)"); var r = window.location.search.substr(1).match(reg); if(r!=null)return unescape(r[2]); return null;}java web 限制同一个用户在不同处登入的更多相关文章
- [转]Java web 开发 获取用户ip
如果通过了多级反向代理的话,X-Forwarded-For的值并不止一个,而是一串IP值,那么真正的用户端的真实IP则是取X-Forwarded-For中第一个非unknown的有效IP字符串. pu ...
- Struts2+AJAX+JQuery 实现用户登入与注册功能。
要求 必备知识 JAVA/Struts2,JS/JQuery,HTML/CSS基础语法. 开发环境 MyEclipse 10 演示地址 演示地址 预览截图(抬抬你的鼠标就可以看到演示地址哦): 关于U ...
- hibernate连接oracle12c数据库报:java.sql.SQLException: ORA-01017: 用户名/口令无效; 登录被拒绝。(用户名/口令在oracle客户端以及cmd命令都能登入)
报错信息: 2017-09-22 15:40:07,354 WARN [org.hibernate.cfg.SettingsFactory] - Could not obtain connection ...
- Struts2+AJAX+JQuery 实现用户登入与注册功能
要求:必备知识:JAVA/Struts2,JS/JQuery,HTML/CSS基础语法:开发环境:MyEclipse 10 关于UI部分请查看下列链接,有详细制作步骤: 利用:before和:afte ...
- Java Web 开发利用Struts2+Spring+mybatis写一个用户登录界面以及简单的数据交互
框架的东西太复杂也难以讲通,直接上代码: 一.首先得配置环境 和导入必要的jar包 有一些重要的如下: Filter文件夹下的SafetyFilter.java model文件夹下的 Global ...
- 【适合公司业务】全网最详细的IDEA里如何正确新建【普通或者Maven】的Java web项目并发布到Tomcat上运行成功【博主强烈推荐】(类似eclipse里同一个workspace下【多个子项目】并存)(图文详解)
不多说,直接上干货! 首先,大家要明确,IDEA.Eclipse和MyEclipse等编辑器之间的新建和运行手法是不一样的. 如果是在Myeclipse里,则是File -> new -> ...
- java web用户登录界面
做这次实验,主要用到了mysql java web 的 内容 实验代码: IUserDao.java package com.jaovo.msg.dao; import java.util.List ...
- Java Web实现用户登录界面
一.学习Java Web需要的技术: Java语言基础:算法基础.常用数据结构.编程规范. 掌握常见的数据结构和实用算法:培养良好的编程习惯. Java面向对象:封装.继承.多态等,面向对象程序设计, ...
- Java Web实现用户登录功能
java web 学习记录一下 mvc结构实现mysql 连接 什么是mvc MVC是模型(model).视图(view).控制(controller)这三个单词上的首字母组成.它是一种应用模型,它的 ...
随机推荐
- Pytorch中stack()方法的理解
Torch.stack() 1. 概念 在一个新的维度上连接一个张量序列 2. 参数 tensors (sequence)需要连接的张量序列 dim (int)在第dim个维度上连接 注意输入的张量s ...
- 暑假算法练习Day4
已经坚持第四天啦,Fighting!!! 1008 数组元素循环右移问题 (20 分) 一个数组\(A\)中存有\(N\)\((>0)\)个整数,在不允许使用另外数组的前提下,将每个整数循环向右 ...
- Java的脚本机制、编译器API
学习 xxl-job 定时任务时了解到基于 JVM 的 Grovvy 脚本语言.搭建 Jenkins 时知道了编译API 1. Java 脚本机制 Java 的脚本 API 可以让我们调用 JavaS ...
- [atARC121F]Logical Operations on Tree
(特判$n=1$的情况) 当确定权值和操作后,如何判定是否合法-- 考虑一个度为1的节点,对其权值即其对应边的边操作分类讨论: $1\or$,显然只需要最后选择这条边即可,一定合法 $1\and$或$ ...
- [51nod1587]半现串
将s所有长度为d/2的子串放进ac自动机中,直接匹配就可以判定半现串了再对其做一个差分,询问一个前缀的半现串个数,在ac自动机上数位dp,f[i][j][0/1]表示走了i步(i位的字符串),走到节点 ...
- [loj3048]异或粽子
先对其求出前缀异或和,然后$o(k)$次枚举,每次选择最大值,考虑如何维护可以全局开一个堆,维护出每一个点的最大值的最大值,那么相当于要在一个点中删去一个点再找到最大值将这些删去的点重新建成一颗tri ...
- 抽象类和接口的区别详解、package和import
1.抽象类和接口以及抽象类和接口的区别. 1.1.抽象类的基础语法(见昨天笔记) 1.2.接口的基础语法 1.接口是一种"引用数据类型". 2.接口是完全抽象的. 3.接口怎么定义 ...
- vue文件引入
<template> <div class="hello"> <h1>{{ msg }}</h1> <!-- <h1&g ...
- Vulnhub-Empire: LupinOne题解
Vulnhub-Empire: LupinOne题解 本靶机为Vulnhub上Empire系列之LupinOne,地址:EMPIRE: LUPINONE 扫描与发现 利用arp-scan命令扫描靶机I ...
- KNN算法实现对iris数据集的预测
KNN算法的实现 import pandas as pd from math import dist k = int(input("请输入k值:")) dataTest = pd. ...