Springboot uses Tomcat as the container to achieve two ways of redirecting http to https!

1 Introduction

This article will introduce how to implement Http to Https redirection through code in Springboot. This article only explains the case of Tomcat as a container, and other containers will come together in the future.

Insert picture description here

2. Related concepts

2.1 What is redirection

The so-called redirection means that you originally wanted to browse address A, but after arriving at the server, the server thinks that the interface of address A is no longer there or you don’t have permission to access it. It doesn’t want you to visit address A; just tell you another address B, Then you go to visit address B.

There are generally two return codes for redirection:

  • 301: Permanent redirection;
  • 302: Temporary redirection.

Check the network details through Chrome and record the redirection of several websites:

website domain name Redirect code URL after redirect
Slowly talk about pumpkin www.pkslow.com 301 https://www.pkslow.com
Google www.google.com 307 https://www.google.com
Apple www.apple.com 307 https://www.apple.com
Alipay www.alipay.com 301 https://www.alipay.com
QQ www.qq.com 302 https://www.qq.com
Baidu www.baidu.com 307 https://www.baidu.com

Note: 307 is also a kind of redirect, which is a new status code.

2.2 Why redirect

Combined with the table I specifically listed above, do you probably think of why this kind of redirection is needed? It is not difficult to find that the above redirects are doing one thing, which is to redirect http to https. The reasons are as follows:

(1) http is not secure, you should use a secure https URL;

(2) But you can't require users to enter https:// every time they enter a website. This is too troublesome, so everyone is accustomed to entering only the domain name, not even www.. Therefore, the user's input is actually to access the http web page, and it needs to be redirected to https to meet the requirements of secure access.

2.3 How to redirect

First of all, the server must support both http and https at the same time, otherwise there will be no redirection. Because https is required to provide support, then why provide http services? Isn't it just unnecessary to visit https directly? The reason has been mentioned before. Everyone is accustomed to only entering a simple domain name to visit. At this time, it is http. If you don't provide http support, users think that your website is already down.

Both protocols provide support, so it is necessary to open two Socket ports. Generally, http is 80 and https is 443. Then you need to redirect all HTTP requests to https. Different servers have different implementations. Now introduce the implementation of Springboot+Tomcat.

3. Springboot Tomcat implements redirection

When Springboot uses Tomcat as the Servlet container, there are two ways to achieve redirection, one is without Spring Security, and the other is with Spring Security. The code structure is as follows:
Insert picture description here
the code of the main class is as follows:

package com.pkslow.ssl;

import com.pkslow.ssl.config.containerfactory.HttpToHttpsContainerFactoryConfig;
import com.pkslow.ssl.config.security.EnableHttpWithHttpsConfig;
import com.pkslow.ssl.config.security.HttpToHttpsWebSecurityConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Import;

@SpringBootApplication
@Import({
    
    EnableHttpWithHttpsConfig.class, HttpToHttpsWebSecurityConfig.class})
//@Import(HttpToHttpsContainerFactoryConfig.class)
@ComponentScan(basePackages = "com.pkslow.ssl.controller")
public class SpringbootSslApplication {
    
    

	public static void main(String[] args) {
    
    
		SpringApplication.run(SpringbootSslApplication.class, args);
	}
	
}

@ComponentScan(basePackages = "com.pkslow.ssl.controller"): The config package is not scanned in because we want to use @Import to control which method is used for redirection. Of course, you can also use other methods to control, such as @ConditionalOnProperty, which will not be discussed here.

  • When Spring Security is not used, @Import(HttpToHttpsContainerFactoryConfig.class) is used;
  • When using Spring Security, use @Import({EnableHttpWithHttpsConfig.class,
    HttpToHttpsWebSecurityConfig.class}).

The content of the configuration file application.properties is as follows:

server.port=443
http.port=80

server.ssl.enabled=true
server.ssl.key-store-type=jks
server.ssl.key-store=classpath:localhost.jks
server.ssl.key-store-password=changeit
server.ssl.key-alias=localhost

Need to specify two ports, server.port is https port; http.port is http port. Note that in the absence of https, server.port refers to the http port.

3.1 Configure Container Factory to implement redirection

The configured class is HttpToHttpsContainerFactoryConfig, the code is as follows:

package com.pkslow.ssl.config.containerfactory;

import org.apache.catalina.Context;
import org.apache.tomcat.util.descriptor.web.SecurityCollection;
import org.apache.tomcat.util.descriptor.web.SecurityConstraint;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.apache.catalina.connector.Connector;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;

@Configuration
public class HttpToHttpsContainerFactoryConfig {
    
    
    @Value("${server.port}")
    private int httpsPort;

    @Value("${http.port}")
    private int httpPort;

    @Bean
    public TomcatServletWebServerFactory servletContainer() {
    
    
        TomcatServletWebServerFactory tomcat =
                new TomcatServletWebServerFactory() {
    
    

                    @Override
                    protected void postProcessContext(Context context) {
    
    
                        SecurityConstraint securityConstraint = new SecurityConstraint();
                        securityConstraint.setUserConstraint("CONFIDENTIAL");
                        SecurityCollection collection = new SecurityCollection();
                        collection.addPattern("/*");
                        securityConstraint.addCollection(collection);
                        context.addConstraint(securityConstraint);
                    }
                };
        tomcat.addAdditionalTomcatConnectors(createHttpConnector());
        return tomcat;
    }

    private Connector createHttpConnector() {
    
    
        Connector connector =
                new Connector(TomcatServletWebServerFactory.DEFAULT_PROTOCOL);
        connector.setScheme("http");
        connector.setSecure(false);
        connector.setPort(httpPort);
        connector.setRedirectPort(httpsPort);
        return connector;
    }
}

createHttpConnector(): This method mainly implements the function of opening http under the premise of https, and configuring the redirected https port.

3.2 Configure Spring security to implement redirection

There are two configuration classes, one for opening the http service and the other for implementing redirection.

The main function of EnableHttpWithHttpsConfig is to open the http service under the premise of having https.

package com.pkslow.ssl.config.security;

import org.apache.catalina.connector.Connector;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

@Configuration
public class EnableHttpWithHttpsConfig {
    
    
    @Value("${http.port}")
    private int httpPort;

    @Component
    public class CustomContainer implements WebServerFactoryCustomizer<TomcatServletWebServerFactory> {
    
    

        @Override
        public void customize(TomcatServletWebServerFactory factory) {
    
    
            Connector connector = new Connector(TomcatServletWebServerFactory.DEFAULT_PROTOCOL);
            connector.setPort(httpPort);
            connector.setScheme("http");
            connector.setSecure(false);
            factory.addAdditionalTomcatConnectors(connector);
        }
    }
}

HttpToHttpsWebSecurityConfig is mainly for the configuration of Spring Security. As we all know, Spring Security is very powerful but very complicated. Key comments have been written in the code:

package com.pkslow.ssl.config.security;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
public class HttpToHttpsWebSecurityConfig extends WebSecurityConfigurerAdapter {
    
    
    @Value("${server.port}")
    private int httpsPort;

    @Value("${http.port}")
    private int httpPort;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
    
    
        //redirect to https - 用spring security实现
        http.portMapper().http(httpPort).mapsTo(httpsPort);
        http.requiresChannel(
                channel -> channel.anyRequest().requiresSecure()
        );

        //访问路径/hello不用登陆获得权限
        http.authorizeRequests()
                .antMatchers("/hello").permitAll()
                .anyRequest().authenticated().and();
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
    
    
        //过滤了actuator后,不会重定向,也不用权限校验,这个功能非常有用
        web.ignoring()
                .antMatchers("/actuator")
                .antMatchers("/actuator/**");
    }
}

Conclusion:

Friends who need to learn materials can click to enter, password: cspp , get it for free!
Insert picture description here

Insert picture description here

Guess you like

Origin blog.csdn.net/m0_45270667/article/details/109220901