The function of single sign-on is still very important in actual application scenarios. Logically, we do not allow a user to perform two operations at the same time. Let’s learn about the single sign-on implementation of SpringMVC.
SpringMVC's interceptor is different from Spring's interceptor. SpringMVC has a unified entry DispatcherServlet. All requests pass through DispatcherServlet, so you only need to make a fuss on the DispatcherServlet. The DispatcherServlet does not have a proxy, and the Controller managed by SpringMVC does not have a proxy.
1. First explore a basic implementation principle: this function is relatively simple, that is, only one user can operate on the same web project at the same time, so here is the discovery of a remote login, and two paths are introduced here. 1. The server discovers that the logged-in user has performed the login operation again through another IP, and then actively pushes a reminder to tell the first user to log in remote login; 2. When the user performs operations, he finds that his account has been squeezed out and there is a remote login. Regarding these two solutions, the first one is more real-time but is still being explored. Let’s focus on the second method below.
2. Implementing the second type is relatively simple. There are two operations. One is to add an extra field to the user's SessionId to store the logged-in user's SessionId, because each request request corresponds to a unique non-repetitive sessionid. Then, using the interceptor technology, intercepting the user's operations. In the interceptor, the relevant url request on the login page is first released, and the other is the login verification request is released. Finally, filter the user. (About user login, when the verification is successful, not only should the user be stored in the Session for login interception verification, but also the Session ID needs to be stored in the corresponding Sessionid in the user table.) For the request request this time, you can obtain the Session and its ID and then compare whether the same with the Sessionid in the database according to this ID, and then pass the release. If the difference is, the offline jump login will be prompted to jump in the login, because there will be a Session in a user connection server operation. As long as the Session expires, the Session ID of each user initiated operation is the same, so it will match the ID stored in the database when logging in. When someone else goes through other devices, use the same account to enter. The session will be re-established when logging in. The Session in the database will refresh the Sessionid in the database, but the Sessionid is still unchanged. However, the Session in the database has changed. Therefore, when verifying whether the Sessionid in the database is consistent in the interceptor, it will fail to intercept the user's operation to achieve the function of single-user login. (A note about Session, when the user first connects to the server, a Session will be created on the server side, and then every operation initiated by the user will carry the id of this Session, and some situations will occur. The user has not operated with the server for a long time. The user logs out and actively makes the Session invalid. The user closes the browser, or restarts the server)
The following is the implementation of the interceptor in SpringMVC
public class SingleUserInterceptor implements HandlerInterceptor {@Autowiredprivate userMapper mapper;public void afterCompletion(HttpServletRequest arg0,HttpServletResponse arg1, Object arg2, Exception arg3)throws Exception {// TODO Auto-generated method stub}public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,Object arg2, ModelAndView arg3) throws Exception {// TODO Auto-generated method stub}public Boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1,Object arg2) throws Exception {String url = arg0.getRequestURI();//If the logged-in page is blocked, release if(url.indexOf("login.jsp")>=0||url.indexOf("new/login")>=0||url.indexOf("checkuser")>=0){return true;}//If the user name exists (that is, login and release) Integer user = (Integer) arg0.getSession().getAttribute("user");if(user!=null){String sessionid = mapper.getUserEntity(Integer.valueOf(user)).getSessionid();if(sessionid.equals(arg0.getSession().getId())){return true;} else{arg1.setStatus(arg1.SC_GATEWAY_TIMEOUT);arg1.setContentType("text/html; charset=utf-8");PrintWriter out = arg1.getWriter();out.println("<html>");out.println("<script>");out.println("alert('Your account is logged in elsewhere, you are forced to go offline')");out.println("window.open ('" + arg0.getContextPath()+ "/new/login','_top');");out.println("</script>");out.println("</html>");// arg0.getRequestDispatcher("login.jsp").forward(arg0, arg1);return false;}}arg0.getRequestDispatcher("login.jsp").forward(arg0, arg1);return false;}}The above code can realize the function of the first logged-in user being squeezed off the line when the same user logs in multiple times. It can realize the function of prompting the account to log in remotely and then jumping to the login page. Here we need to explain the key points of this simple alert prompt function. If this alert is to appear, it must be able to end the request. Then the response printing function outputs the alert prompt statement, so the commented jump statement cannot exist. If there is, the alert prompt statement will not be issued, because your operation does not end correctly but is forwarded or redirected to other operations. Whether it is correct or not, it will be output from other actions to the page, so your response print statement will not appear. So the correct way is: the intercepting request is not released (returnfalse), and the request is still the original request and will not jump. The printing information of the response back to the page can be displayed. As for jumping to the login page, you can use: out.println("window.open('"+arg0.getContextPath()+"/new/login','_top');"); to implement that an action request is executed in a section of js output by the response, pointing to the login page.
The above code has basically been regarded as a single user login function, but you will find that the operation of ajax request does not point to the login page when logging in remote location, and there is no prompt information. Let me explain the reason first, because your ajax is making an asynchronous request, and the requested url is also matched in the processor mapper, so it will be regarded as the request is successful (the return status code is 200). The js statement printed in the above response will become the successful request in success, and the return value. You can try to comment out the above sentence: arg1.setStatus(arg1.SC_GATEWAY_TIMEOUT); At this time, some other operations need to be performed. The first is the statement arg1.setStatus(arg1.SC_GATEWAY_TIMEOUT); its function is to set the status code returned by response. The above settings indicate that the status code 504 will be returned to represent a request error. At this time, the ajax request will no longer respond in the success method, but will respond to the ajax error method. Therefore, you only need to execute the corresponding method in the ajax error, for example:
$.ajax({ url:'new/msd2', success:function(a){ alert(a); }, error:function(rs){ if(rs.status==504){ document.write(rs.responseText); } } });When the ajax request is intercepted because of a remote login, set arg1.setStatus(arg1.SC_GATEWAY_TIMEOUT); the return status of the request can be changed to 504. Then the error method responds. When it is determined that the status is the status code you set, document.write(rs.responseText); responseText is the js statement printed to the front desk in the interceptor. For these statements to be executed, the document.write(); method needs to write the code to the dom to make it take effect. At this point, all requests and single sign-in for asynchronous ajax requests have basically been implemented.
Leave this article only to record the key code, ideas and principles of operations
Summarize
The above is all about the implementation of single sign-on in SpringMVC interceptor, I hope it will be helpful to everyone. If there are any shortcomings, please leave a message to point it out. Thank you friends for your support for this site.