Deep thinking on changing redirect from https to http

Keywords: Java Spring

background

  1. Service deployment and jump are shown as follows:

  2. The user requests to load the specified application through Alibaba cloud through http. The application returns the jump path (status 302), but the jump path is http (not https), so it cannot be accessed
    2.1 jump pseudo code:

    // ModelAndView
    mv.setViewName(WebCst.REDIRECT + "/admin/sso/login");
    

    2.2 screenshot of browser jump

Conclusion summary

  1. The Location returned to the browser with nginx load is https because nginx has been processed. See the following for key configurations

    proxy_set_header    Host   $host;
    proxy_redirect http:// https://;
    

    1.1 use the trace command of arthas to observe the line, and the Location returned directly by the application is http://localhost:8232/exp-admin/admin/sso/login

    	watch org.apache.catalina.connector.Response toAbsolute -x 2
    
  2. After replacing nginx with SLB, the load returned to the browser becomes http because SLB lacks corresponding configuration
    2.1 SLB related configurations: https://help.aliyun.com/document_detail/97646.html

How is the jump Location generated

  1. The background is developed by springboot. The following analysis is based on springboot

  2. Let's first show how spring MVC works

    2.1 our jump settings are: mv.setViewName(WebCst.REDIRECT + "/ admin/sso/login"); Combined with the above figure, guess to jump according to the view

    2.2 the view parser ContentNegotiatingViewResolver parses the view through resolveViewName to get the jump view: RedirectView, and calls its render to jump

  3. Jump analysis with RedirectView#render

    3.1 the following figure shows the Location obtained by distinguishing whether it is compatible with http1.0(http10Compatible)
    (1) The default is compatible with http1.0, so response.sendredirect (encoded URL);

    (2) Response.sendRedirect (encoded URL) will eventually trigger the sendRedirect method of tomcat's org.apache.catalina.connector.Response

    public void sendRedirect(String location, int status) throws IOException {
    	locationUri = toAbsolute(location);
    	setStatus(status);
        setHeader("Location", locationUri); //Set the location of the jump
    }
    

    3.2 entry generated by jump Location: org.apache.catalina.connector.Response#toAbsolute

    // Obtain the protocol, IP and port information from the request, and then splice it with the set relative path
    protected String toAbsolute(String location) {
    	String scheme = request.getScheme();
        String name = request.getServerName();
        int port = request.getServerPort();
        redirectURLCC.append(scheme, 0, scheme.length());
        redirectURLCC.append("://", 0, 3);
        redirectURLCC.append(name, 0, name.length());
        if ((scheme.equals("http") && port != 80)
            || (scheme.equals("https") && port != 443)) {
            redirectURLCC.append(':');
            String portS = port + "";
            redirectURLCC.append(portS, 0, portS.length());
        }
        redirectURLCC.append(location, 0, location.length());
    }
    

Where is the protocol information generated in the Request

  1. According to the call stack, when the ConnectionHandler processes the connection, it performs differential processing according to SocketEvent

  2. Process open in Http11Processor_ The read event preprocesses the request
    public SocketState service(SocketWrapperBase<?> socketWrapper)
        throws IOException {
    	prepareRequestProtocol();  //Set to http1.1
    	prepareRequest(); //Processing protocol (http or https)
    	getAdapter().service(request, response); //Dispatcher after calling
    }
    
  3. Judge whether SSL is enabled in prepareRequest. If it is enabled, it is https
    private void prepareRequest() throws IOException {
    	if (protocol.isSSLEnabled()) {
            request.scheme().setString("https");
        }
    }
    

nginx settings for jump

  1. Jump description on nginx official website: https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_redirect
  2. Sets the text changed in the Location header field of the proxy server response.
    2.1 suppose the proxy server returns the header field "Location: http://localhost:8000/two/some/uri/ ”. The instruction proxy_ redirect http://localhost:8000/two/ http://frontend/one/ ; Rewrite this string to "Location: http://frontend/one/some/uri/ ”.
    2.2 the configuration on nginx that can jump normally is as follows to convert http to Https
    proxy_set_header    Host   $host;
    proxy_redirect http:// https://;
    
  3. Local application SSL configuration: https://zhuanlan.zhihu.com/p/31385073
    #https port number
    server.port: 443
    #Path to the certificate
    server.ssl.key-store: tomcat.keystore
    #Certificate password, please change it to your own certificate password
    server.ssl.key-store-password: 123456
    #Keystore type
    server.ssl.keyStoreType: PKCS12
    #Certificate alias
    server.ssl.keyAlias: tomcat
    

Posted by Hitman2oo2 on Tue, 30 Nov 2021 09:23:41 -0800