Home > Software design >  Creation of a Tomcat Connector Creates Two Instances of the Same Spring Boot App - How to access HTT
Creation of a Tomcat Connector Creates Two Instances of the Same Spring Boot App - How to access HTT

Time:10-10

My Spring Boot application contains a login verification system that enforces users to register their credentials and verify their email by sending a confirmation form with an "Activate Now" button in their account. Upon the verification completion, the user may enter with their verified credentials in my application.

The latter is implemented on HTTPS on https:localhost:8443 with SSL enabled along with Spring Security.

My problem is as follows:

I want to expose actuator metrics but since I have HTTPS enabled the omonymous URL will be https:localhost:8443/actuator. I want to access that URL from http:localhost:8080/actuator and for that reason I created a second Tomcat connector which somehow solves my problem since I am receiving responce from POSTMAN.

But... As soon as, I create the second Tomcat connector I have to proceed to the verification process all over again from the start which means that the second Tomcat connector, created a second instance of my application, but running on a different port. I am providing a diagram just to help you somehow with my issue.

I want to access the http:localhost:8080/actuator while maintaining the verification process which took place already from the start of my application on https:localhost:8443. Is that possible???

Application Diagram

Security Config Class

package com.andrekreou.iot.authentication.security;

import com.andrekreou.iot.authentication.user.ApplicationUserService;
import lombok.AllArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
@AllArgsConstructor
@EnableWebSecurity
public class ApplicationSecurityConfig {

    private final ApplicationUserService applicationUserService;

    private final BCryptPasswordEncoder bCryptPasswordEncoder;

    @Bean
    protected SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                .requiresChannel()
                    .antMatchers("/greeting","/actuator/prometheus")
                    .requiresInsecure()
                .and()
                .authorizeRequests()
                    .antMatchers("/api/v*/registration/**","/register*","/login","/registration","/registration-complete","/greeting").permitAll()
                    //.antMatchers("/show-news-contents").hasRole(ADMIN.name())
                    .anyRequest()
                    .authenticated()
                    .and()
                .formLogin()
                    .loginPage("/login")
                    .usernameParameter("email")
                    .permitAll()
                    .defaultSuccessUrl("/",true)
                    .failureUrl("/login-error")
                .and()
                .logout()
                    .logoutUrl("/logout")
                    .clearAuthentication(true)
                    .invalidateHttpSession(true)
                    .deleteCookies("JSESSIONID","Idea-2e8e7cee")
                    .logoutSuccessUrl("/login");

        return http.build();
    }

    @Bean
    public AuthenticationManager authenticationManager(
            AuthenticationConfiguration authenticationConfiguration) throws Exception {
        return authenticationConfiguration.getAuthenticationManager();
    }

    @Bean
    public DaoAuthenticationProvider daoAuthenticationProvider() {
        DaoAuthenticationProvider provider =
                new DaoAuthenticationProvider();
        provider.setPasswordEncoder(bCryptPasswordEncoder);
        provider.setUserDetailsService(applicationUserService);
        return provider;
    }
}

Main Class

package com.andrekreou.iot;

import org.apache.catalina.connector.Connector;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

@SpringBootApplication
@EnableJpaRepositories
public class IotApplication {

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

    @Bean
    public ServletWebServerFactory servletContainer(@Value("${server.http.port}") int httpPort) {
        Connector connector = new Connector(TomcatServletWebServerFactory.DEFAULT_PROTOCOL);
        connector.setPort(httpPort);

        TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
        tomcat.addAdditionalTomcatConnectors(connector);
        return tomcat;
    }
}

Application.properties

#Server properties for HTTPS configuration
server.ssl.enabled=true
server.ssl.key-store-type=PKCS12
server.ssl.key-store=classpath:local-ssl.p12
server.ssl.key-store-password=<password>
server.ssl.key-password=<password>
server.servlet.context-path=/
server.ssl.key-alias=local_ssl
server.port=8443
server.http.port=8080

CodePudding user response:

As M. Deinum suggests, it is preferable to avoid such implementations. You have to configure your application.properties file by adding these two lines.

management.server.ssl.enabled=false
management.server.port=8080

Then remove that server.http.port=8080 as well as ServletWebServerFactory bean declared in your Main class. Finally, add the following path in your antMatchers line in your Security Config class just after authorizeRequests().

This way you will have both /actuator/prometheus in 8443 and 8080 port.

Hope this helps!!!

  • Related