Java防止用戶同一時間重復登錄(包括異地登錄)

有時候我們在做登錄模塊過程中難免會遇到這種問題,即使我們給用戶進行了多重判斷,比如:用戶名,管理員,驗證碼,一系列的判斷… 你是否真正考慮到用戶的體驗,比如不能讓用戶在同一時間,同一個瀏覽器重復登錄問題,同時也包括不同瀏覽器登錄(異地登錄)問題。
這些都是我們應該去考慮的。如果是用Spring 框架的話,Spring security 是可以實現防止用戶重復登錄的問題的,但我這里并沒有用到框架,因為我這里不需要做太高的限制。

我們可以利用 Servlet三大域對象 request、session、application(ServletContext)中的ServletContext,它是一個全局的儲存信息的空間,服務器啟動后就被創建,服務器停止后才銷毀。
request,一個用戶可有多個;session,一個用戶一個;而servletContext,所有用戶共用一個。所以,為了節省空間,提高效率,ServletContext中,要放必須的、重要的、所有用戶需要共享的線程又是安全的一些信息。
思路:我們將用戶的登錄信息保存在context里, 然后利用監聽器HttpSessionListener監聽每一個登錄用戶的登錄情況,實時監控session。

Servlet:

/*登錄方法*/
public void login(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException{String username = request.getParameter("username");//登錄名String password = request.getParameter("password");//密碼HttpSession session=request.getSession();response.setCharacterEncoding("UTF-8");PrintWriter out=response.getWriter();SystemUsertable usertable = service.login(username);//SystemUsertable 自己封裝存放用戶信息的類if (usertable != null) {if (usertable.getPassword().equals(password)) {session.setAttribute("userid", usertable.getUserid());session.setAttribute("username", usertable.getUsername());} else {out.write("<html><head><meta charset='utf-8'></head><script>alert('密碼錯誤');window.location.href='../jsp/login.jsp';</script>");}}else {out.write("<html><head><meta charset='utf-8'></head><script>alert('用戶不存在');window.location.href='../jsp/login.jsp';</script>");}ServletContext context = session.getServletContext();@SuppressWarnings("unchecked")Map<String, Object> loginMap = (Map<String, Object>) context.getAttribute("loginMap");if (loginMap == null) {loginMap = new HashMap<String, Object>();}for (String key : loginMap.keySet()) {int result=usertable.getUserid();String day = "";day = String.valueOf(result);if (day.equals(key)) {if (session.getId().equals(loginMap.get(key))) {out.write("<html><head><meta charset='utf-8'></head><script>alert('在同一地點重復登錄');window.location.href='../jsp/login.jsp';</script>");} else {out.write("<html><head><meta charset='utf-8'></head><script>alert('異地已登錄,請先退出登錄');window.location.href='../jsp/login.jsp';</script>");}}else{}}loginMap.put(String.valueOf(usertable.getUserid()),session.getId());context.setAttribute("loginMap", loginMap);// 將用戶保存在session當中session.setAttribute("usertable", usertable);// session 銷毀時間session.setMaxInactiveInterval(10*60);out.write("<html><head><meta charset='utf-8'></head><script>alert('登錄成功');window.location.href='../jsp/main.jsp';</script>");}

這時候我們需要寫一個監聽器,監聽每一個登錄用戶的登錄情況。首先去web.xml 配置監聽器:

/*監聽器存放路徑*/
<listener>  <listener-class>  com.day.listener.SessionListener</listener-class>  
</listener>

Listener:

/*監聽器*/
public class SessionListener implements HttpSessionListener  {@Overridepublic void sessionCreated(HttpSessionEvent httpSessionEvent) {//創建// TODO Auto-generated method stub}@Overridepublic void sessionDestroyed(HttpSessionEvent httpSessionEvent) {//銷毀// TODO Auto-generated method stubHttpSession session = httpSessionEvent.getSession();SystemUsertable user = (SystemUsertable) session.getAttribute("usertable");if (user != null) {ServletContext application = session.getServletContext();@SuppressWarnings("unchecked")Map<String, Object> loginMap = (Map<String, Object>) application.getAttribute("loginMap");loginMap.remove(user.getUserid());application.setAttribute("loginMap", loginMap);session.removeAttribute("usertable");}}
}

最后需要對它的退出登錄進行處理,退出時銷毀session, 清除用戶登錄信息。

 /*退出登錄*/
public void loginOut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{HttpSession session = request.getSession();String id = session.getId();if (session != null) {try {session.removeAttribute("usertable");String user= id; if (session.getAttribute(user) != null) {session.removeAttribute(user);}ServletContext context = session.getServletContext();@SuppressWarnings("unchecked")Map<String, Object> loginMap = (Map<String, Object>) context.getAttribute("loginMap");if (loginMap != null) {loginMap = new HashMap<String, Object>();}context.setAttribute("loginMap", loginMap);} catch (Exception e) {e.printStackTrace();}}request.getRequestDispatcher("/jsp/login.jsp").forward(request, response);
}

這樣子就可以把登錄的用戶信息清除掉,用戶可去其他瀏覽器登錄亦或是繼續登錄。其實,這些大多可以根據自己的需求而定,代碼可以是固定的,但思想是活的。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/443367.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/443367.shtml
英文地址,請注明出處:http://en.pswp.cn/news/443367.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

jquery點擊彈出播放視頻并顯示遮罩層

最近在做視頻播放的時候&#xff0c;發現用jquery的播放視頻可以很好的實現我所需要的效果。在之前請把插件引用進來&#xff0c;廢話不多說&#xff0c;代碼如下&#xff1a; <!DOCTYPE html> <html><head><meta charset"utf-8"><meta …

JS實現圖片循環滾動

之前在前端的時候有遇到這樣一個問題&#xff0c;實現 JS 圖片的循環滾動&#xff0c;然后鼠標移入的時候停止滾動&#xff0c;鼠標移開繼續滾動&#xff0c;這里無非就是設置了一個定時器&#xff0c;鼠標移上時清除定時器達到滾動停止的目的&#xff0c;鼠標移開時重設定時器…

有趣的滾動條

今天在搭前端頁面的時候&#xff0c;UI給過來的一個自定義的滾動條&#xff0c;要求必須與設計的一樣&#xff0c;覺得有點有趣&#xff0c;現在記錄一下。 效果圖&#xff1a; 具體代碼是這樣的&#xff1a; /*字體太長&#xff0c;這里我就減少一些*/ <div class"l…

查詢分頁的幾種sql語句

sql server 中的分頁查詢sql語句不跟mysql 一樣&#xff0c;mysql 用 limit 可以實現查詢sql分頁。如&#xff1a; select * from news where id>(select id from news limit 250000,1) limit 10; //相對執行效率高 select * from news limit 250000,10;mysql 中 limit總是…

c#解決在數據表格中無法顯示秒數問題

在查詢日期的時候&#xff08;年月日時分秒&#xff09;&#xff0c;發現丟失了秒&#xff0c;在這里我用的是自己 封裝的Vo類里面的時間轉換&#xff0c;沒有把秒數查詢出來&#xff0c;在Vo動不了手&#xff0c;我還不能對Controller 動手了&#xff1f; 查詢&#xff1a; 更…

解決 idea 復制jsp 文件過來頁面報404

今天在做功能的時候把另外一個jsp文件復制過來&#xff0c;發現頁面一直報404&#xff0c;咋搞的&#xff0c;檢查路徑沒有問題&#xff0c;報404這個就奇葩了&#xff0c;后面經過一番“洗腦”&#xff0c;才發現jsp文件復制過來少了一個特別重要的步驟&#xff0c;那就是重新…

解決ckeditor富文本在layui 彈框中大小字體等下拉不顯示

css <div class"layui-input-inline" style"width:1100px;"><div class"noticeContent"><textarea id"Introduce1" name"處分結果" class"form-control" style"z-index:19991015">&…

C# DateTime.Compare判斷兩個DateTime 日期是否相等

DateTime t1 DateTime.Now.Date; //2020/8/4 0:00:00 DateTime t2 Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"));//得到2020/8/4 16:24:54 DateTime t3 Convert.ToDateTime(t1.AddHours(16).AddMinutes(24).AddSeconds(t2.Second).AddM…

解決git上傳提交的時出現:Please tell me who you are.問題

今天安裝好git后&#xff0c;創建新項目&#xff0c;當git上傳提交時出現了一個問題&#xff0c;如下&#xff1a; Commit failed - exit code 128 received, with output: *** Please tell me who you are.Rungit config --global user.email "youexample.com"git …

vue解決v-for報錯 [vue/valid-v-for]Custom elements in iteration require ‘v-bind:key‘ directives

v-for報錯 [vue/valid-v-for]Custom elements in iteration require ‘v-bind:key’ directives.eslint-plugin-vue 原因&#xff1a;這是因為我安裝的enlint插件&#xff0c;它會對代碼的規范進行檢查。我這里用到v-for&#xff0c;但它是需要key值的&#xff0c;當不根據它的…

vscode中如何運行git

在vscode 中運行git 指令&#xff0c;發現報錯。 這是因為還沒有進行安裝git &#xff0c;所以這個指令對于vscode 來說是沒有辦法識別的&#xff0c;這時&#xff0c;我們就要進行下載安裝git。 第一步&#xff1a;下載git 去到git 官網&#xff1a; 點擊下載&#xff0…

通過nginx在window下部署項目

1…安裝nginx 首先&#xff0c;進入nginx 的官網&#xff0c;下載nginx&#xff0c;安裝nginx 通過&#xff0c;https://nginx.org/ 鏈接進入 Mainline version&#xff1a;開發版&#xff0c;mainline 目前主力在做的版本 Stable version&#xff1a;最新穩定版&#xff0c;生…

C# 字符串逗號分隔存到List 數組(互相轉換)

List 數組用逗號分隔成字符串 var ptCancelFileUpload context.PtCancelFileUpload.Where(x > x.Recordstatus ! RecordStatusType.InActive.ToStr()).Select(x > x.Taskcode).ToList();if (ptCancelFileUpload.Count > 0){string resultStr "";foreach …

代碼塊概述

代碼塊&#xff1a;在Java中&#xff0c;使用{}括起來的代碼被稱為代碼塊。 根據其位置和聲明的不同&#xff0c;可以分為&#xff1a; 局部代碼塊:局部位置,用于限定變量的生命周期。 構造代碼塊:在類中的成員位置,用{}括起來的代碼。每次調用構造方法執行前&#xff0c;都…

Android常見命令

1&#xff09;adb指令 adb kill-server 殺死adb服務 adb start-server 開啟adb服務 cd desktop&#xff08;假如安裝包在桌面&#xff09; adb install 應用名.apk 安裝應用 adb uninstall 應用包名 …

final,finally和finalize的區別

&#xfeff;&#xfeff;final&#xff1a;最終的意思&#xff0c;可以修飾類&#xff0c;成員變量&#xff0c;成員方法 修飾類&#xff0c;類不能被繼承 修飾變量&#xff0c;變量是常量 修飾方法&#xff0c;方法不能被重寫 finally&…

Collection集合總結

&#xfeff;&#xfeff;Collection|--List 有序,可重復|--ArrayList底層數據結構是數組&#xff0c;查詢快&#xff0c;增刪慢。線程不安全&#xff0c;效率高|--Vector底層數據結構是數組&#xff0c;查詢快&#xff0c;增刪慢。線程安全&#xff0c;效率低|--LinkedList底層…

排序算法之冒泡排序,選擇排序

public class Sort {public static void main(String[] args) {int[] arr { 24, 69, 80, 57, 13 };bubbleSort(arr);selectSort(arr);for (int s : arr) {System.out.print(s "/");}}//冒泡排序public static void bubbleSort(int[] arr) {for (int i 0; i < a…

java設計模式之裝飾模式

裝飾模式&#xff1a;又名包裝(Wrapper)模式&#xff0c;裝飾模式以對客戶端透明的方式擴展對象的功能&#xff0c;是繼承關系的一個替代方案。 裝飾模式可以在不創造更多的子類的模式下&#xff0c;將對象的功能加以擴展。 經典代碼&#xff1a; //裝飾模式interface Phone…

Hibernate與 MyBatis的比較

第一章 Hibernate與MyBatis Hibernate 是當前最流行的O/R mapping框架&#xff0c;它出身于sf.net&#xff0c;現在已經成為Jboss的一部分。 Mybatis 是另外一種優秀的O/R mapping框架。目前屬于apache的一個子項目。 MyBatis 參考資料官網&#xff1a;http://www.mybatis.or…