仅仅思路,这是springsecurety的

package com.dbapp.fly.config.security;import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;import com.dbapp.fly.entity.SysUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.stereotype.Component;//登录用户认证通过后,显示登录成功页面前,做的操作。
@Component
public class MyAuthenctiationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {private static final Logger logger = LoggerFactory.getLogger(MyAuthenctiationSuccessHandler.class);// key为sessionId,value为HttpSession,使用static,定义静态变量,使之程序运行时,一直存在内存中。// 保存所有已经登录用户的会话(每个浏览器一个会话)public static HashMap<String, HttpSession> sessionMap = new HashMap<String, HttpSession>();@Autowired// @Qualifier("sessionRegistry")private SessionRegistry sessionRegistry;// @Bean(name="sessionRegistry",value="sessionRegistry")@Bean// @Bean(name="sessionRegistry")public SessionRegistry getSessionRegistry() {return new SessionRegistryImpl();}@Overridepublic void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,Authentication authentication) throws ServletException, IOException {// 1.登录认证成功后,获取用户名//(只能在认证成功通过后,才能获得sc,不然在CustomUserService implements UserDetailsService的loadUserByUsername方法中是第二次才能获取到)SecurityContext sc = SecurityContextHolder.getContext();String currentuser = ((SysUser) sc.getAuthentication().getPrincipal()).getUserName();logger.info("当前登录用户:" + currentuser);// 2.先判断用户是否重复登录Iterator<Entry<String, HttpSession>> iterator = sessionMap.entrySet().iterator();while(iterator.hasNext()) {Map.Entry<String, HttpSession> entry = iterator.next();HttpSession session = entry.getValue();// 2.1 判断session中所包含的用户名称是否有当前登录用户String username = SessionUtil.getUserName(session);if (currentuser.equals(username)) {logger.info("用户:" + currentuser + "已经在其它地方登录过,将踢除!");SessionUtil.expireSession(session);logger.info("删除的会话:"+entry.getKey());// 2.2 从sessionMap中踢除会话iterator.remove();// 2.3 从sessionRegistry中踢除会话sessionRegistry.removeSessionInformation(session.getId());}}/*//以下这种方法会引起java.util.ConcurrentModificationException: null 错误,    HashMap// 2.先判断用户是否重复登录for (Entry<String, HttpSession> entry : sessionMap.entrySet()) {HttpSession session = entry.getValue();// 2.1 判断session中所包含的用户名称是否有当前登录用户String username = SessionUtil.getUserName(session);if (currentuser.equals(username)) {logger.info("用户:" + currentuser + "已经在其它地方登录过,将踢除!");SessionUtil.expireSession(session);logger.info(entry.getKey());sessionMap.remove(entry.getKey());//这里会引起同步错误sessionRegistry.removeSessionInformation(session.getId());}}*/// 3.将当前session保存到sessionMap中logger.info("将当前会话:" + request.getSession().getId() + ",保存到sessionMap");sessionMap.put(request.getSession().getId(), request.getSession());for (Entry<String, HttpSession> entry : sessionMap.entrySet()) {logger.info("显示已经保存的sessionMap:Key: " + entry.getKey() + " Value: " + entry.getValue());}// 4.打印所有认证通过的用户(包含重复登录的,不过上面已经踢除了)List<Object> principals = sessionRegistry.getAllPrincipals();List<String> usersNamesList = new ArrayList<String>();for (Object principal: principals) {if (principal instanceof SysUser) {usersNamesList.add(((SysUser) principal).getUserName());}}logger.info("已经认证通过的用户数:"+usersNamesList.size()+",     已经认证通过用户:"+usersNamesList.toString());// response.sendRedirect("/");super.onAuthenticationSuccess(request, response, authentication);}}
package com.dbapp.fly.config.security;import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;//启动类加上注解@ServletComponentScan,这样才能扫描到监听器
//@WebListener
public class MySessionListner implements HttpSessionListener {private static final Logger logger = LoggerFactory.getLogger(MySessionListner.class);/*** 新建session时(打开浏览器访问登录页面时,服务器会创建一个新的session)*/@Overridepublic void sessionCreated(HttpSessionEvent httpSessionEvent) {System.out.println("创建session");}/*** 删除session时(退出系统)*/@Overridepublic void sessionDestroyed(HttpSessionEvent httpSessionEvent) {logger.info("销毁session时");MyAuthenctiationSuccessHandler.sessionMap.remove(httpSessionEvent.getSession().getId());}}
package com.dbapp.fly.config.security;import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
public class MywebConfig implements WebMvcConfigurer {@Beanpublic ServletListenerRegistrationBean listenerRegist() {ServletListenerRegistrationBean srb = new ServletListenerRegistrationBean();srb.setListener(new MySessionListner());System.out.println("listener");return srb;}
}
package com.dbapp.fly.config.security;import java.util.Enumeration;
import java.util.List;import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;import com.dbapp.fly.entity.SysUser;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.session.SessionInformation;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.core.userdetails.User;public class SessionUtil {private static SecurityContext attribute;/*** 根据当前session获取当前登录用户对象* @param session* @return guser*/public static SysUser getUser(HttpSession session) {try {attribute = (SecurityContext) session.getAttribute("SPRING_SECURITY_CONTEXT");SysUser principal = (SysUser) attribute.getAuthentication().getPrincipal();return principal;} catch (Exception e) {}return null;}/*** 根据当前session获取当前登录用户ID* @param session* @return guser*/public static Long getUserId(HttpSession session) {try {attribute = (SecurityContext) session.getAttribute("SPRING_SECURITY_CONTEXT");SysUser principal = (SysUser) attribute.getAuthentication().getPrincipal();return principal.getId();} catch (Exception e) {}return null;}/*** 根据session获取用户名称* @param session* @return void*/public static String getUserName(HttpSession session) {try {attribute = (SecurityContext) session.getAttribute("SPRING_SECURITY_CONTEXT");SysUser principal = (SysUser) attribute.getAuthentication().getPrincipal();return principal.getUserName();} catch (Exception e) {e.printStackTrace();}return null;
}/*** 根据session获取count* session中包含一个count键默认为null,可以用来统计登录次数* @param session* @return void*/public static void count(HttpSession session) {ServletContext context = session.getServletContext();System.out.println("sessionid:"+session.getId()+",的count是:"+context.getAttribute("count"));}/*** 辨别用户是否已经登录,如果已经登录就不能登录了。** @param request* @param sessionRegistry* @param loginedUser*/public static void deleteSameUser(HttpServletRequest request, SessionRegistry sessionRegistry, User loginedUser) {SecurityContext sc = (SecurityContext) request.getSession().getAttribute("SPRING_SECURITY_CONTEXT");List<SessionInformation> sessionsInfo;sessionsInfo = sessionRegistry.getAllSessions(sc.getAuthentication().getPrincipal(), true);String currentSessionId;if (null != sessionsInfo && sessionsInfo.size() == 0) {sessionRegistry.registerNewSession(request.getSession().getId(), sc.getAuthentication().getPrincipal());sessionsInfo = sessionRegistry.getAllSessions(sc.getAuthentication().getPrincipal(), false);}currentSessionId = sessionsInfo.get(0).getSessionId();List<Object> o = sessionRegistry.getAllPrincipals();for (Object principal : o) {if (principal instanceof User && (loginedUser.getUsername().equals(((User) principal).getUsername()))) {List<SessionInformation> oldSessionsInfo = sessionRegistry.getAllSessions(principal, false);if (null != oldSessionsInfo && oldSessionsInfo.size() > 0 && !oldSessionsInfo.get(0).getSessionId().equals(currentSessionId)) {for (SessionInformation sessionInformation : sessionsInfo) {//当前session失效sessionInformation.expireNow();sc.setAuthentication(null);sessionRegistry.removeSessionInformation(currentSessionId);//throw new GeneralServerExistException(ErrorMessage.ALONG_LOGIN_ERROTR.toString());}}}}}/*** 会话销毁(剔除前一个用户)** @param , SysMessageService sysMessageService*/public static void expireSession(HttpSession session) {session.invalidate();}/*** 剔除前一个用户** @param request* @param sessionRegistry* @param loginedUser* @param , SysMessageService sysMessageService*/public static void dropPreviousUser2(HttpServletRequest request, SessionRegistry sessionRegistry, SysUser loginedUser) {List<SessionInformation> sessionsInfo = null;//登录以后session里才会加入键名为"SPRING_SECURITY_CONTEXT"的字段SecurityContext sc = (SecurityContext) request.getSession().getAttribute("SPRING_SECURITY_CONTEXT");if(sc!=null) {System.out.println("!!!!!!!!!!!!"+sc.getAuthentication().getPrincipal().toString());//获取当前登录用户的会话信息集合sessionsInfo = sessionRegistry.getAllSessions(sc.getAuthentication().getPrincipal(), false);if (sessionsInfo.size() > 0) {//当前会话IDString  currentSessionId = sessionsInfo.get(0).getSessionId();//获取所有已经登录的用户List<Object> o = sessionRegistry.getAllPrincipals();for (Object principal : o) {//当登录用户的名字和已经登录用户的名字相同,也就是登录用户已经登录过了。if (principal instanceof User && (loginedUser.getUserName().equals(((User) principal).getUsername()))) {//获取已经登录用户的会话信息集合List<SessionInformation> oldSessionsInfo = sessionRegistry.getAllSessions(principal, false);//如果会话信息不为空且会话信息的ID不等于当前会话IDif (null != oldSessionsInfo && oldSessionsInfo.size() > 0 && !oldSessionsInfo.get(0).getSessionId().equals(currentSessionId)) {//遍历已经登录用户的会话信息,并设置过期,即删除sessionfor (SessionInformation sessionInformation : oldSessionsInfo) {//旧用户的session失效//send message//sysMessageService.sendMessage(((User) principal).getUsername(), new SysMessage(null, Consts.NOTIFICATION_TYPE_HADLOGIN_CONTENT, 5, Consts.NOTIFICATION_ACCEPT_TYPE_HADLOGIN));sessionInformation.expireNow();}}}}}}}/*** session 失效** @param request* @param sessionRegistry*/public static void expireSession(HttpServletRequest request, User user, SessionRegistry sessionRegistry) {List<SessionInformation> sessionsInfo = null;if (null != user) {List<Object> o = sessionRegistry.getAllPrincipals();for (Object principal : o) {if (principal instanceof User && (user.getUsername().equals(((User) principal).getUsername()))) {sessionsInfo = sessionRegistry.getAllSessions(principal, false);}}} else if (null != request) {SecurityContext sc = (SecurityContext) request.getSession().getAttribute("SPRING_SECURITY_CONTEXT");if (null != sc.getAuthentication().getPrincipal()) {sessionsInfo = sessionRegistry.getAllSessions(sc.getAuthentication().getPrincipal(), false);sc.setAuthentication(null);}}if (null != sessionsInfo && sessionsInfo.size() > 0) {for (SessionInformation sessionInformation : sessionsInfo) {//当前session失效sessionInformation.expireNow();sessionRegistry.removeSessionInformation(sessionInformation.getSessionId());}}}public void showsession(HttpServletRequest request) {//获取session  HttpSession   session   =   request.getSession();    // 获取session中所有的键值  Enumeration<String> attrs = session.getAttributeNames();  // 遍历attrs中的while(attrs.hasMoreElements()){// 获取session键值  String name = attrs.nextElement().toString();// 根据键值取session中的值  Object vakue = session.getAttribute(name);// 打印结果 System.out.println("--sessionID"+session.getId());System.out.println("--名字:" + name +"-----\n");System.out.println("--值:" + vakue +"--------\n");}}
}

一个用户只能登录一次相关推荐

  1. ASP.NET MVC实现一个用户只能登录一次 单用户登录

    现在许多网站都要求登录后才能进行进一步的操作,当不允许多用户同时登录一个帐号时,就需要一种机制,当再登录一个相同的帐号时,前面登录的人被挤下线,或者禁止后面的人登录.这里实现的是前一种功能. 网上有许 ...

  2. 《指定一个用户只能在特定的时间里不能登陆》『罗斌原创』

    <指定一个用户只能在特定的时间里不能登陆> 使用有管理员权限的用户登陆(administrator),进入命令模式下以GUEST这个用户为列 如果需要设置这个GUEST帐户从周一到周五的早 ...

  3. oracle 创建一个用户,只能访问指定的对象

    今天在开发接口时候,需要给接口开发公司提供一个ORACLE 用户,只能访问指定的表或视图,把过程记录到此 1.创建一个ORACLE 的用户 create user username identifie ...

  4. (Java)实现一个用户密码登录的弹窗界面

    目录 一.前言 二.涉及到的知识点代码 三.代码部分 四.程序运行结果(弹出) 一.前言 1.本代码是我在上学时写的,有一些地方没能完美实现,请包涵也请多赐教! 2.本弹窗界面可以根据简单的要求进行输 ...

  5. linux 没有权限登录,CentOS中让一个用户没有登录权限

    一.还未建立用户时,可以使用以下命令 1,groupadd groupname useradd -g groupname username -s /bin/false   #-s为默认shell,不给 ...

  6. 防止用户重复登录解决方案

    前一段时间碰到一个需求:一个账号只能登录一次,不能重复登录问题. 在网上找了下,大概有两种解决方案: 1.通过数据库状态位判断该用户是否已经登录. 2.利用session监听器监听每一个登录用户的登录 ...

  7. 一个手机里登录2个微信号(微信双开)

    正常来说,使用微信的客户端,一个手机只能登录一个微信号. 所以,另一个微信号就需要第三方的工具来实现. 我的环境:android (苹果的APPStore 好像没有我使用的这款软件) 重点来了,这是款 ...

  8. WordPress查看上次用户何时登录插件When Last Login

    如果你的 WordPress 站点是多人联合管理和开放用户注册功能的大型博客网站,那么想要查看上次用户何时登录您的 WordPress 网站,建议安装这款轻巧 When Last Login 插件.该 ...

  9. java中限制多人登录的_Spring Boot + Spring Security 防止用户在多处同时登录(一个用户同时只能登录一次)及源码分析...

    网上很多文章的实现方法写得比较复杂 这里介绍一个简单的方法. 实现 @Configuration @EnableWebSecurity public class SecurityConfigurati ...

最新文章

  1. python面向对象开发(类的属性-精讲
  2. 计算feature map大小
  3. Android View的事件分发机制解析
  4. Debian 新负责人发表演讲:Debian 的现状与面临的一些问题
  5. aspx隐藏前台控件div_c# – 代码隐藏页面无法“查看”aspx页面中声明的任何项目/控件...
  6. Spring Boot2 整合 Shiro ,两种方式全总结!
  7. 计算机黑屏策略,小黑w7系统诊断策略服务已被禁用的还原教程
  8. 《史无前例!编程语言python斩获最有发展第一与排行榜第三!》深入 Python 流程控制
  9. winform 读取用户控件的变量_winform中用户控件之间的传值
  10. 实现一个闹钟_iOS 14 闹钟:为啥这么难用?
  11. 机械工程师手册 pdf版下载_机械设计问题 简明手册介绍的还是很全面详尽的(附PDF手册)...
  12. iPhone手机越狱不只是为了安装盗版应用、越狱的十大好处
  13. win10更改hosts文件
  14. JS利用for多重循环制作9*9乘法表
  15. 初夏小谈:结构体内存对齐详解
  16. 【Python】胡渊鸣的99行代码——冰雪奇缘
  17. mtatlas mysql_MHA-Atlas-MySQL高可用(下)
  18. Mac电脑上如何关闭屏幕时间
  19. 【web学习之Mysql】数据库-----查询操作------大全
  20. 【听】你会杀死那个胖子吗?功利与道德的选择

热门文章

  1. python批量剪辑音频pydub
  2. window系统如何禁止运行指定程序
  3. awss3mysql_Amazon aws s3 加速
  4. 父盒子内子盒子居中的方法
  5. PHP时间差七个小时怎么回事,php 怎么解决8小时时间差的问题
  6. android发送QQ邮件(带附件)
  7. 实现软件GPS的软硬件设计讨论
  8. latex 论文致谢
  9. 如鹏网C语言也能干大事精华帖
  10. javamail 读取邮箱邮件并下载附件