最近有一個需求,不容許多個設備同時登錄一個帳號,因爲我仍是一個初學者,對於這個需求我能想到的解決辦法就是建立一個全局的map集合,用來存儲用戶的帳號以及登錄成功時的session(這裏存session是爲了方便數據處理),在session中設置一個logined的屬性來標識用戶的登錄狀態,爲防止惡意篡改和用戶退出後能夠在其餘地方登錄(從map集合中去掉登錄信息),logined屬性的值設置用戶的帳號。javascript
下面我添加一個用來學習的小項目:css
項目採用ssm框架,maven工程,結構以下:html
ssm框架的配置這裏就再也不贅述了,須要實現以上需求,咱們須要本身寫一個類繼承HttpSessionListener,因爲咱們是要在session被銷燬的同時在map集合中一樣去除登錄信息,故這裏須要重寫HttpSessionListener的sessionDestroyed方法,在web.xml文件中對該監聽進行配置。項目完整代碼以下:java
控制層jquery
LoginController.javaweb
package com.lzy.controller; import java.util.List; import javax.servlet.http.HttpServletRequest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.servlet.ModelAndView; import com.lzy.bean.Acc; import com.lzy.service.LoginService; import com.lzy.util.LoginMap; @Controller public class LoginController { @Autowired LoginService ls; @RequestMapping("/login") public ModelAndView RSLogin() { ModelAndView mav=new ModelAndView(); mav.setViewName("login"); return mav; } @RequestMapping("/logining") public ModelAndView logining( @RequestParam(value="username",defaultValue="1") String username, @RequestParam(value="password",defaultValue="1") String password, HttpServletRequest req ) { System.out.println(username+" "+password+" "); ModelAndView mav=new ModelAndView(); if(LoginMap.isExist(username)) { System.out.println(username+"已登錄..."); System.out.println(LoginMap.getMessHttpSession(username).getId()); mav.setViewName("logined"); mav.addObject("username", username); }else { List<Acc> accountList = ls.getAccount(username,password); if(accountList!=null&&!accountList.isEmpty()) { req.getSession().setAttribute("logined", username); LoginMap.setMess(username,req.getSession()); System.out.println(LoginMap.getMessHttpSession(username).getAttribute("logined")); mav.setViewName("success"); mav.addObject("username",username); }else { mav.setViewName("register"); } } return mav; } @RequestMapping("/register1") public ModelAndView register( @RequestParam("username") String username, @RequestParam("password") String password ) { Acc acc=new Acc(); acc.setUsername(username); acc.setPassword(password); int num = ls.insertAccount(acc); System.out.println(num); ModelAndView mav=new ModelAndView(); if(num>0) { mav.setViewName("login"); }else { mav.setViewName("register"); } return mav; } @ResponseBody @RequestMapping("/quit") public String quit(HttpServletRequest req) { if(req.getSession(false).getAttribute("logined")!=null) { String username = (String)req.getSession(false).getAttribute("logined"); LoginMap.remove(username); req.getSession(false).invalidate(); return "invaliate successful..."; }else { return "this session not found..."; } } @ResponseBody @RequestMapping("/writeToSession") public String testSession(@RequestParam("username") String username) { System.out.println(username); LoginMap.getMessHttpSession(username).setAttribute("writed", "my word..."); return (String)LoginMap.getMessHttpSession(username).getAttribute("writed"); } }
test請求控制(只是用來比較值觀的觀察數據是否插入完成的,無關緊要)Test1.javaajax
package com.lzy.controller; import javax.servlet.http.HttpServletRequest; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import com.lzy.util.LoginMap; @Controller public class Test1 { @ResponseBody @RequestMapping("/test") public String Test( @RequestParam("username") String username, HttpServletRequest req ) { return (String)LoginMap.getMessHttpSession(username).getAttribute("logined") +" "+ LoginMap.getMessHttpSession(username).getAttribute("writed"); } }
服務層:spring
LoginService.javabootstrap
package com.lzy.service; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.lzy.bean.Acc; import com.lzy.bean.AccExample; import com.lzy.bean.AccExample.Criteria; import com.lzy.dao.AccMapper; @Service public class LoginService { @Autowired AccMapper am; public List<Acc> getAccount(String username, String password) { AccExample example=new AccExample(); Criteria ec = example.createCriteria(); ec.andUsernameEqualTo(username); ec.andPasswordEqualTo(password); return am.selectByExample(example); } public int insertAccount(Acc record) { return am.insertSelective(record); } }
util包(工具類):session
LoginMap.java
建立全局map集合存儲用戶登錄信息,提供了一些簡單的獲取session(getMessHttpSession()),添加鍵值對到map集合(setMess()),經過用戶名從map集合裏移除該鍵值對(remove()),根據用戶名判斷map集合中用戶是否存在(isExist())幾個經常使用的方法。
package com.lzy.util; import java.util.HashMap; import java.util.Map; import javax.servlet.http.HttpSession; public class LoginMap { private static Map<String, HttpSession> map=new HashMap<>(); public static Map<String, HttpSession> getMap() { return map; } public static HttpSession getMessHttpSession(String username) { return map.get(username); } public static void setMess(String username,HttpSession httpSession) { map.put(username, httpSession); } public static boolean remove(String username) { HttpSession judge = map.get(username); if(judge!=null) { return map.remove(username, judge); } return true; } public static boolean isExist(String username) { if(map.get(username)!=null) { return true; } return false; } }
LoginSessionDestroyed.java
重寫destroyed方法後的類
package com.lzy.util; import javax.servlet.http.HttpSession; import javax.servlet.http.HttpSessionEvent; import javax.servlet.http.HttpSessionListener; /** * * @author admin * session listener,we need delete this session message from LoginMap when this session destroyed * we override sessionDestroyed method */ public class LoginSessionDestroyed implements HttpSessionListener{ @Override public void sessionCreated(HttpSessionEvent se) { } @Override public void sessionDestroyed(HttpSessionEvent se) { HttpSession session = se.getSession(); System.out.println("Destroyed:"+session.getId()); System.out.println("Destroyed:"+session.getAttribute("logined")); System.out.println("Destroyed:"+LoginMap.getMap().size()); System.out.println("Destroyed:"+LoginMap.remove((String)session.getAttribute("logined"))); System.out.println("Destroyed-:"+LoginMap.getMap().size()); System.out.println("Destroyed-:"+session.getId()); } }
把下面這段代碼放到web.xml中:
<!-- session listener,we need delete this session message from LoginMap when this session destroyed --> <listener> <listener-class>com.lzy.util.LoginSessionDestroyed</listener-class> </listener>
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>ssm_lzy</display-name> <!-- 啓動spring的容器 --> <!-- needed for ContextLoaderListener --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param> <!-- Bootstraps the root web application context before servlet initialization --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- springmvc --> <!-- The front controller of this Spring Web application, responsible for handling all application requests --> <servlet> <servlet-name>dispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <!-- Map all requests to the DispatcherServlet for handling --> <servlet-mapping> <servlet-name>dispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <!-- session listener,we need delete this session message from LoginMap when this session destroyed --> <listener> <listener-class>com.lzy.util.LoginSessionDestroyed</listener-class> </listener> </web-app>
到這裏就完成了全部的編寫以及配置。
結果:
aaa 123
aaa
test:aaa
test:null
aaa 123
aaa已登錄...
1B121BDC2695FAE387A37C74250D119D
Destroyed:1B121BDC2695FAE387A37C74250D119D
Destroyed:aaa
Destroyed:0
Destroyed:true
Destroyed-:0
Destroyed-:1B121BDC2695FAE387A37C74250D119D
aaa 123
aaa
aaa 123
aaa已登錄...
DE36495191F6922262AF6F3597EC3162
test:aaa
test:null
test:aaa
test:null
aaa 123
aaa已登錄...
DE36495191F6922262AF6F3597EC3162
aaa
test:aaa
test:my word...
Destroyed:DE36495191F6922262AF6F3597EC3162
Destroyed:aaa
Destroyed:0
Destroyed:true
Destroyed-:0
Destroyed-:DE36495191F6922262AF6F3597EC3162
aaa 123
aaa
test:aaa
test:null
aaa 123
aaa已登錄...
0B97575FDF99060F32DDD0C03F2AB377
aaa
aaa 123
aaa已登錄...
0B97575FDF99060F32DDD0C03F2AB377
test:aaa
test:my word...
aaa 123
aaa已登錄...
0B97575FDF99060F32DDD0C03F2AB377
bbb 123
1
bbb 123
bbb
test:bbb
test:null
bbb
Destroyed:0B97575FDF99060F32DDD0C03F2AB377
Destroyed:aaa
Destroyed:1
Destroyed:true
Destroyed-:1
Destroyed-:0B97575FDF99060F32DDD0C03F2AB377
Destroyed:3191C4C94610844DE7796E681C6B4BC9
Destroyed:bbb
Destroyed:0
Destroyed:true
Destroyed-:0
Destroyed-:3191C4C94610844DE7796E681C6B4BC9
最後再貼如下前臺代碼吧:
login.jsp
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>login</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="static/css/bootstrap.css"> <link rel="stylesheet" href="static/css/login.css"> <script src="static/js/jquery-3.2.1.js"></script> <script type="text/javascript"> var setHUN=function(obj){ $("#hiddUsername").val($(obj).val()); } </script> </head> <body> <form action="http://192.168.0.199:8080/testSession1/logining" method="post"> <span>username:</span><input type="text" id="username" name="username" oninput="setHUN(this)"><br> <span>password:</span><input type="password" name="password"><br> <input type="submit" value="login"> </form> <br> <form action="http://192.168.0.199:8080/testSession1/quit" method="post"> <input type="text" id="hiddUsername" name="username"> <input type="submit" id="quit" value="quit"> </form> <script src="static/js/bootstrap.js"></script> <script src="static/js/login.js"></script> <!-- 重用,退出功能 --> <script src="static/js/quit.js"></script> </body> </html>
register.jsp
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>register</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="static/css/bootstrap.css"> <link rel="stylesheet" href="static/css/login.css"> </head> <body> <form action="http://192.168.0.199:8080/testSession1/register1" method="post"> <span>username:</span><input type="text" name="username"><br> <span>password:</span><input type="password" name="password"><br> <input type="submit" value="register"> </form> <br> <input type="button" id="quit" value="quit"> <script src="static/js/jquery-3.2.1.js"></script> <script src="static/js/bootstrap.js"></script> <!-- 重用,退出功能 --> <script src="static/js/quit.js"></script> </body> </html>
success.jsp
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>success</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="static/css/bootstrap.css"> </head> <body> <h1>logining successful...</h1> <p><%=request.getAttribute("username") %></p> <form action="http://192.168.0.199:8080/testSession1/test" method="post"> <input type="hidden" name="username" value=<%=request.getAttribute("username") %>> <input type="submit" value="test"> </form> <a href="http://192.168.0.199:8080/testSession1/writeToSession?username=<%=request.getAttribute("username") %>">write to Session</a> </body> </html>
logined.jsp
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>logined</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="static/css/bootstrap.css"> </head> <body> <h1>logined...</h1> <p><%=request.getAttribute("username") %></p> <form action="http://192.168.0.199:8080/testSession1/test" method="post"> <input type="hidden" name="username" value=<%=request.getAttribute("username") %>> <input type="submit" value="test"> </form> <a href="http://192.168.0.199:8080/testSession1/writeToSession?username=<%=request.getAttribute("username") %>">write to Session</a> </body> </html>
fail.jsp
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>fail</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="static/css/bootstrap.css"> </head> <body> <h1>logining fail...</h1> </body> </html>
testSession.js
$.ajax({ url:"http://192.168.0.199:8080/testSession1/testSession", type:"post", error:function(){}, success:function(mess){ console.log(mess); } });
若是您看到了這篇文章,恰巧有更好的辦法,不妨在下方留言👀