I have been idle recently and have no projects to do, so I sorted out some common problems that I encountered in my daily work. First of all, I thought about the problem of multi-user login restrictions. Let me give some thoughts on this issue.
Related readings:
Java Web Development Perfect Solution to Prevent Multiple Users from Repeated Login
1. Design Scene
1) A user is not allowed to log in multiple places at the same time
2) The user has logged in at A. It is now allowed to log in from B, but it will squeeze out A (considering that the user has been to B due to some circumstances after logging in at A, but still wants to continue the previous work, so he needs to log in to the system)
3) After squeezing A out of B, the system will give a prompt when A does other operations. The user logs in elsewhere. If the password may be leaked if it is not for his own operation, please change the password.
2. Idea map
When each user logs in, we usually store user information into the session so that the system can easily obtain the user's basic information when the user performs operations. However, this session is private and is only visible to the current user (if you agree that the user will get different sessions, which is the root cause of why multiple users can log in). Then the question comes, how can a user know whether he is online when logging in? I believe you are smart, you have already thought that this is not easy. Isn’t the problem of storing online user information in a public place? After checking online, the solution is completely different, and it is roughly the following two types.
1) Identify online users in the database
2) Store in application
After many considerations, we will find that Solution 1 needs to solve many difficult problems (user abnormal exit and future modification status, frequent access to the database affects performance, etc.), which is obviously inappropriate for you who require perfection. So we adopted Solution 2, saving online user information into the application, and the specific design is as follows.
1) Login flow chart
2) Operation flow chart after being squeezed out
3. Code
1) Login method
@RequestMapping(value = "/login", method = RequestMethod.POST)public String login(String userName, String password, RedirectAttributes redirectAttributes, HttpServletRequest request) {//Judge whether the user has been online and processed (remove it is online) String loginLimite = limitLogin.loginLimite(request, userName);//Judge whether the user name and password are correct String result = userService.login(userName, password); if (result.equals("success")) {request.getSession().setAttribute("now_user", userService.findByUserName(userName));//Create token and verify String jwtToken = tokenService.createUserAuthToken(userService.findByUserName(userName));//Create tokenSystem.out.println(jwtToken);UserAuthenticationToken authToken = tokenService.retrieveUserAuthToken(jwtToken);//token parses System.out.println(authToken.isAuthenticated());System.out.println("id = " + UserAuthenticationToken.getCurrentToken().getUserUuid());//The user is disconnected and redirects to the saved link after logging in. Object url = request.getSession().getAttribute("redirect_link"); if (url != null) {request.getSession().removeAttribute("redirect_link");return "redirect:" + url.toString();}return "index";}redirectAttributes.addFlashAttribute("message", result);return "redirect:/other/toLogin";}2) Log in to determine whether it is already online
@Service@Transactionalpublic class LimiteLogin {private static Logger log = Logger.getLogger(SessionListener.class);private static Map<String, String> loginUserMap = new HashMap<>();//Storage online users private static Map<String, String> loginOutTime = new HashMap<>();//Storage user exclusion time @Autowiredprivate UserService userService;public String loginLimite(HttpServletRequest request, String userName) {User user = userService.findByUserName(userName);String sessionId = request.getSession().getId();for (String key : loginUserMap.keySet()) {//The user has logged in to another place if (key.equals(user.getUserName()) && !loginUserMap.containsValue(sessionId)) {log.info("User:" + user.getUserName() + ", in " + DateUtil.dateFormat(new Date(), "yyyy-MM-dd HH:mm:ss") + "Excluded! ");loginOutTime.put(user.getUserName(), DateUtil.dateFormat(new Date(), "yyyy-MM-dd HH:mm:ss"));loginUserMap.remove(user.getUserName());break;}}loginUserMap.put(user.getUserName(), sessionId);request.getSession().getServletContext().setAttribute("loginUserMap", loginUserMap);request.getSession().getServletContext().setAttribute("loginOutTime", loginOutTime);return "success";}}3) Login interceptor (no login to jump to login page)
public class LoginInterceptor extends HandlerInterceptorAdapter {@Overridepublic boolean preHandle(HttpServletRequest request,HttpServletResponse response, Object handler) throws Exception {HttpSession session = request.getSession();User user = (User) session.getAttribute("now_user");if (session.getAttribute("now_user") == null) {response.sendRedirect(request.getContextPath() + "/other/toLogin");return false;}//Multi-user login restriction judgment, and give a prompt message boolean isLogin = false;if (user != null) {Map<String, String> loginUserMap = (Map<String, String>) session.getServletContext().getAttribute("loginUserMap");String sessionId = session.getId();for (String key : loginUserMap.keySet()) {//The user has logged in to another place if (key.equals(user.getUserName()) && !loginUserMap.containsValue(sessionId)) {isLogin = true;break;}}}if (isLogin) {Map<String, String> loginOutTime = (Map<String, String>) session.getServletContext().getAttribute("loginOutTime");session.setAttribute("mess", "User:" + user.getUserName() + ", in " + loginOutTime.get(user.getUserName()) + "Logined elsewhere!");loginOutTime.remove(user.getUserName());session.getServletContext().setAttribute("loginUserMap", loginOutTime);response.sendRedirect(request.getContextPath() + "/other/toLogin");return false;}return super.preHandle(request, response, handler);}@Overridepublic void postHandle(HttpServletRequest request,HttpServletResponse response, Object handler,ModelAndView modelAndView) throws Exception {super.postHandle(request, response, handler, modelAndView);}@Overridepublic void afterCompletion(HttpServletRequest request,HttpServletResponse response, Object handler, Exception ex)throws Exception {super.afterCompletion(request, response, handler, ex);}}4) When the session is destroyed, clear the key value pairs saved in loginUserMap
public classSessionListener implements HttpSessionListener {private static Logger log = Logger.getLogger(SessionListener.class);@Overridepublic void sessionCreated(HttpSessionEvent event) {}@Overridepublic void sessionDestroyed(HttpSessionEvent event) {HttpSession session = event.getSession();String sessionId = session.getId();//When the session is destroyed, clear the key value pair saved in loginUserMap User user = (User) session.getAttribute("now_user");if (user != null) {Map<String, String> loginUserMap = (Map<String, String>) event.getSession().getServletContext().getAttribute("loginUserMap");if(loginUserMap.get(user.getUserName()).equals(sessionId)){log.info("clean user from application: " + user.getUserName());loginUserMap.remove(user.getUserName());event.getSession().getServletContext().setAttribute("loginUserMap", loginUserMap);}}}}5) web.xml
<!-- session listener Multi-user login restrictions, log out to clear session information while clearing user login information stored in the application--><listener><listener-class>com.service.limitelogin.SessionListener</listener-class></listener>
6) Page code (used to clear the session information of the squeezed user while giving a prompt, otherwise the prompt information will be displayed all the time)
<script type="text/javascript">$(document).ready(function () {var message='${mess}';if (message != "") {$.ajax({type: 'GET',async: false,cache: false,url: '/other/clearUserSession',dataType: '',data: {},success: function (data) {}});$('#mess').html(message);}});</script>7) Clear the user session code
/*** Multi-user login restrictions, clear session information (login information, prompt information)** @param request* @return*/@ResponseBody@RequestMapping(value = "/clearUserSession")public String clearUserSession(HttpServletRequest request) {HttpSession httpSession = request.getSession();//httpSession.invalidate();httpSession.removeAttribute("now_user");httpSession.removeAttribute("mess");return "success";}The development work is completed here
4. Operation results
The above is the implementation method of Java multi-user login restrictions introduced to you by the editor. I hope it will be helpful to you. If you have any questions, please leave me a message and the editor will reply to you in time. Thank you very much for your support to Wulin.com website!