java使用过滤器和监听器防止用户重复登录

您所在的位置:网站首页 qq电脑登陆显示不能重复登陆 java使用过滤器和监听器防止用户重复登录

java使用过滤器和监听器防止用户重复登录

2023-12-26 22:57| 来源: 网络整理| 查看: 265

一.任务描述

相信很多小伙伴都使用QQ聊天工具,那是否遇到过这样的场景呢?当在一台电脑上已经登录QQ,此时因为某些原因需要在另一台电脑再登录相同号码的QQ,登录成功后会发现之前电脑上的QQ下线了。这就是QQ限制了同一个号码在电脑上不能重复登录,我们的Web程序也可以进行重复登录的限制,那么本次任务就是用过滤器和监听器来解决重复登录问题。具体任务如下:

1、未登录时不能访问主界面。

2、登录后,登录信息存储到session中。

3、监听器监听session属性值变化。

4、一个浏览器中已经登录,如果在另一个浏览器中重复登录,则清除前次登录信息。

二.效果演示

1.运行web应用程序,进入谷歌浏览器登录界面

谷歌浏览器

 2.此时为第一次进入程序,输入一个用户名密码。(这里输入用户名为haiexijun)

谷歌浏览器

 3.点击提交按钮登录,显示登录成功。

谷歌浏览器

 4.我如果用另外一个客户端登录,模拟异地登陆。上面第一次用的是谷歌浏览器,这次用edge浏览器输入用户名。

edge浏览器 edge浏览器

 5.在edge浏览器上点击提交,则会在edge上成功登陆.

edge浏览器 edge浏览器

 6.返回谷歌浏览器,刷新登陆界面后。会显示账号被异地登录了,并要求重新登录了。

谷歌浏览器

 7.点击确定会让你重新登录

 8.并且可以在谷歌浏览器重新登录,并成功登陆

 

 9.然后再一次回到edge浏览器再刷新则会被提醒账号被异地登录,并提醒重新登陆:

 

 很简单吧!

10.之前相同用户名异端登录提醒的功能算是实现了,最后测试一下不同用户名则不会出现提示。

在edge浏览器输入用户名为zcbad,和谷歌浏览器的haiexijun不是一个用户了,回到谷歌浏览器刷新则不会出现异端登录的提醒。完美实现!

 

三.代码实现 1.在idea中用maven创建一个webapp项目,项目结构如图:

2.然后在webapp目录下创建一个login.html的用户登录界面: login 用户名: 密码:

用post请求传到的名为login的servlet处理请求。

3.设置一个过滤器loginFilter,对url为/login的请求进行过滤: package org.example.filter; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @WebFilter(filterName = "loginFilter",urlPatterns = "/login") public class loginFilter implements Filter { @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { //获取httpServletRequest对象 HttpServletRequest request=(HttpServletRequest) servletRequest; //获取全局对象 ServletContext context=request.getServletContext(); //获取userName String userName=request.getParameter("username"); //设置一个用户列表,用于记录用户登录 if (context.getAttribute("userList")==null){ //如果第一次登录这个客户端,就创建列表,加入用户 List userList = new ArrayList(); userList.add(userName); context.setAttribute("userList",userList); }else { //如果不是第一次登录 List userList= (List) context.getAttribute("userList"); //就判断用户列表中是否有此用户 if (!userList.contains(userName)){ //如果不包含该用户,就添加进去 userList.add(userName); } } //获取此客户端的session //session列表 HttpSession session= request.getSession(); if (context.getAttribute("sessionMap")==null){ Map sessionMap=new HashMap(); sessionMap.put(userName,session); context.setAttribute("sessionMap",sessionMap); }else { Map sessionMap= (Map) context.getAttribute("sessionMap"); if (!sessionMap.containsKey(userName)){ sessionMap.put(userName,session); } //测试sessionMap System.out.println("======sessionMap======"); for (Map.Entry entry:sessionMap.entrySet()){ System.out.println(entry.getKey()+":"+entry.getValue()); } System.out.println("======================="); } //给session设置username session.setAttribute("userName",userName); //判断是否为同一个session Map sessionMap = (Map) context.getAttribute("sessionMap"); HttpSession session1=sessionMap.get(userName); if (session1==session){ filterChain.doFilter(servletRequest,servletResponse); }else { HttpServletResponse response=(HttpServletResponse) servletResponse; response.sendRedirect("/logout.html"); //用于销毁session session.invalidate(); } } }

我先把用户名加入一个arraylist列表中,其实这一步可有可无啦(一开始写的,忘了删)。创建名为sessionMap的map集合,把每次登录所创建的不同session存进去,键为userName,值为当前应用的session。以便后续监听和判断。

网上很多人是通过sessionid来判断是否是同一个客户端上的登录,但我直接比较不同客户端登录时服务器创建的session是否为同一个对象(不同客户端登录,服务器创建的session就是不同的,直接比较是否为同一个httpsession对象就行了)。

如果判断当前session和sessionMap中保存的同用户名的session为同一个session,则为同一个客户端同一个用户登录。否则异地登录,则刷新就要重新登陆。

4.同时,还要写一个监听器sessionListener: package org.example.listener; import javax.servlet.ServletContext; import javax.servlet.http.*; import java.util.Map; public class sessionListener implements HttpSessionAttributeListener, HttpSessionListener { @Override public void attributeAdded(HttpSessionBindingEvent event) { //获取session HttpSession session=event.getSession(); //通过session来获取context上下文对象 ServletContext context=session.getServletContext(); //获得用户名 String userName= (String) session.getAttribute("userName"); //判断sessionId是否于之前登录时sessionMap里存的相同 Map sessionMap = (Map) context.getAttribute("sessionMap"); String sessionId=sessionMap.get(userName).getId(); if (!session.getId().equals(sessionId)){ sessionMap.remove(userName); } sessionMap.put(userName,session); } @Override public void sessionDestroyed(HttpSessionEvent se) { System.out.println("destory"); } }

这个监听器的作用是监听session的属性的变化,在session属性发生改变时触发该监听器。第一次开启应用时会触发一次。后来每在已登录的客户端以外的客户端上登录也会产生新的session,也就是会有session的属性被设置,从而也触发监听器,,进行判断sessionid,然后更改sessionMap。

5.login.java的servlet: package org.example.servlet; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @WebServlet("/login") public class login extends HttpServlet { @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.getRequestDispatcher("/index.html").forward(req,resp); } }

通过了过滤器后,到login.java的servlet这里,这一步也就是简简单单的把请求转发到index.html页面了,此时就登录成功了!

6.index.html代码: index 登陆成功! 7.异地登录时跳转到logout.html: logout logout alert("你尚未登录,或者账号在异地登陆,请重新登陆!"); window.location.href="http://localhost:8888/login.html"; 8.web.xml的配置: Archetype Created Web Application org.example.listener.sessionListener

其他配置:

9.maven依赖配置: 4.0.0 org.example mylogin 1.0-SNAPSHOT war mylogin Maven Webapp http://www.example.com UTF-8 1.7 1.7 junit junit 4.11 test javax.servlet javax.servlet-api 4.0.1 provided javax.servlet.jsp javax.servlet.jsp-api 2.3.3 javax.servlet.jsp.jstl jstl-api 1.2 javax.servlet servlet-api javax.servlet.jsp jsp-api org.glassfish.web jstl-impl 1.2 javax.servlet servlet-api javax.servlet.jsp jsp-api javax.servlet.jsp.jstl jstl-api mylogin maven-clean-plugin 3.1.0 maven-resources-plugin 3.0.2 maven-compiler-plugin 3.8.0 maven-surefire-plugin 2.22.1 maven-war-plugin 3.2.2 maven-install-plugin 2.5.2 maven-deploy-plugin 2.8.2 这是我第一个博客,可能这次写得并不好,但以后我还有很多机会,我会继续努力,坚持越写越好的。


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3