This article is suitable for students who have a certain understanding of session and cookie. It mainly introduces the tomcat session generation mechanism, OAUTH2 authentication process and spring method parameter mapping processing, etc. based on the clue of problem location

Background:

  • The session: Because HTTP is stateless, the Web container supports session management to store user status information. When a client requests a Web application, if request.getSession() is called during processing, The Web container first searches for the session based on the JSESSIONID uploaded in the URL or cookie (by default, this value can be set to the requestedSessionId field of the Request object). If it cannot obtain the session object, it automatically creates a session object. When a session expires or is abandoned, the server terminates the session
protected Session doGetSession(Boolean create) {// Skip some codeif(requestedSessionId ! = null) { session = manager.findSession(requestedSessionId); String sessionId = getRequestedSessionId(); Session = manager.createsession (sessionId); // Create a cookie and write responseif(session ! = null && context.getServletContext() .getEffectiveSessionTrackingModes() .contains(SessionTrackingMode.COOKIE)) { Cookie cookie = ApplicationSessionCookieConfig.createSessionCookie( context, session.getIdInternal(), isSecure()); response.addSessionCookieInternal(cookie); } // omit some code}Copy the code
  • Cookies: To enable the server to identify different clients, the client saves the data returned by the server through cookies (for example, JSESSIONID. The default cookie key of the Tomcat server session is JSESSIONID). The server then finds the session created for the client using the cookie data placed in the HTTP header when the client requests it. Session cookies are classified into session cookies and persistent cookies. Session cookies exist during a valid session. The persistent cookie server sets HTTP header cache fields to indicate the client cache policy
  • Oauth2: request is an open standard, allows users to make the third party applications to access the user is stored on a web site of the private resources (such as photos, video, the contact list), without having to provide the user name and password to the third party applications, can be used in micro public authentication service environment, and the service is oauth2 authentication

People dig holes and people fall. It’s the fault of the frame

Problem Features:

  • A new JSESSIONID is generated after an interface request is discovered and written back to the browser in the form of cookies. As a result, subsequent request authentication fails and must be performed
  • The intercall relationship between services is complex, so this function needs to be tested in the development environment

Problem locating process:

  • We learned from the communication that the problem still existed after all the requested method body codes were cancelled in the previous positioning process, so we missed a good opportunity to check the problem code (in fact, the method parameters had problems) and locate the problem as soon as possible
  • Wondering if the nginx session persistence policy is causing the problem (but this policy should affect all requests, not just a single request), look at the nginx.conf configuration, which does not load balance the service
  • If the request path contains the auth sensitive field, nginx has made a special configuration for the request path. However, the configuration is very simple, and the auth field in the request path is deleted
  • It was suspected that some peripheral code had rewritten the cookie, but the search failed to find the relevant code
  • The process of service authentication is summarized (see top picture, which is abbreviated, public authentication service is deleted and directly connected to OAuth2), and the description is as follows: 1) The authentication logic is encapsulated in a public Filter to intercept all requests and determine whether they are logged in. 2) If the JSESSIONID is not uploaded or the session and token information cannot be found in Redis based on it, 3) The client invokes the login interface: The server invokes oAUTH2 (there is a public authentication service), writes the authentication token information into redis, and then writes the server JSESSIONID back to the client cookie. The tomcat default JSESSIONID is reused here, which is assumed to reuse the request getRequestedSessionId method, which directly takes the JSESSIONID submitted by the client cookie. JSESSIONID = JSESSIONID = JSESSIONID = JSESSIONID = JSESSIONID = JSESSIONID 4) The client continues to invoke the previous service interface with the JSESSIONID returned by authentication. The JSESSIONID in Tomcat is inconsistent with the uploaded JSESSIONID. According to the uploaded JSESSIONID, tomcat cannot find the corresponding session. 5) There are other logics in the authentication process, which are deleted here, so as not to affect the main process
  • After combing, it was found that although the two keys were the same, but the values were different, and they would interfere with each other, so it was suspected that the peripheral code called getSession method, and the search code failed to find it
  • Check request path corresponding method, the method used in the session parameter, but method is not used in the body, this parameter associated with the parameter value of the spring automatic mapping mechanism (see ServletRequestMethodArgumentResolver), The getSession method is called in the process of assigning the session value, and the related cookies are created and written back to the client because the corresponding session cannot be found in Tomcat
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { Class<? > paramType = parameter.getParameterType(); // Omit some codeif(HttpSession.class.isAssignableFrom(paramType)) { HttpSession session = request.getSession(); // omit some code}}Copy the code
  • Delete parameters, test, problem solving

Pit:

  • Do not use Tomcat’s session mechanism (such as getSession or session parameters) in the business methods of services that use this authentication mechanism, otherwise this problem will occur

Solution:

  • To solve this problem, remove the session parameter
  • Change the JSESSIONID of the authentication mechanism to a different name, but the change is too big, there may be other pits
  • The distributed Session (Token) solution combines the Tomcat session management mechanism with the distributed Session (Token)
  • JWT token authentication is adopted. The server does not save the token but only performs authentication and refreshing
Welcome to follow my wechat official account