SpringBoot security allowed path permit all not working in Spring Reactive application - spring-boot

I have an SpringBoot reactive[Webflux] application which has the below mentioned security configuration. Recently I have integrated a module which uses spring-boot-starter-web dependency. After integrating the API's mentioned in the security.config.allowed-paths configuration is not accessible. could you please help me with the solution.
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.method.configuration.EnableReactiveMethodSecurity;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.web.server.SecurityWebFilterChain;
import org.springframework.security.web.server.util.matcher.NegatedServerWebExchangeMatcher;
import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatchers;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsConfigurationSource;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
import java.util.Arrays;
#Configuration
#EnableWebFluxSecurity
#EnableReactiveMethodSecurity
public class SecurityConfig {
#Value("${security.config.allowed-paths}")
private String[] allowedPaths;
#Bean
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
http.csrf().requireCsrfProtectionMatcher(getURLsForIgnoredCSRF())
.and().cors().configurationSource(corsConfigSource()).and()
.authorizeExchange()
.pathMatchers(allowedPaths).permitAll()
.pathMatchers(HttpMethod.OPTIONS).permitAll();
http.headers().frameOptions().disable();
return http.build();
}
public NegatedServerWebExchangeMatcher getURLsForIgnoredCSRF() {
return new NegatedServerWebExchangeMatcher(exchange -> ServerWebExchangeMatchers.pathMatchers(allowedPaths).matches(exchange));
}
#Bean
CorsConfigurationSource corsConfigSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOriginPatterns(Arrays.asList("https://*.sampleexmple.com"));
configuration.setAllowedMethods(Arrays.asList("GET","POST","OPTIONS"));
configuration.setAllowCredentials(true);
configuration.setAllowedHeaders(Arrays.asList("*"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
Thanks in advance.
Suraj Jannu

Related

Parameter 1 of constructor in required a bean of type that could not be found

I've been stuck for a while now. I'm modifying my Spring Security project by adding Jwt. Currently, I'm trying to make the JwtEncoder and JwtDecoder work in SecurityConfig, I need RSAPrivateKey and RSAPublicKey for these methods. To get these Key-values I'm using a Record with #ConfigurationProperties annotation. But Getting this Record into the SecurtyConfig gives me some problems:
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 1 of constructor in com.ssl.app.security.config.SecurityConfig required a bean of type 'com.ssl.app.security.config.RsaKeyProperties' that could not be found.
Action:
Consider defining a bean of type 'com.ssl.app.security.config.RsaKeyProperties' in your configuration.
This is my SecurtyConfig
import com.nimbusds.jose.jwk.JWK;
import com.nimbusds.jose.jwk.JWKSet;
import com.nimbusds.jose.jwk.RSAKey;
import com.nimbusds.jose.jwk.source.ImmutableJWKSet;
import com.nimbusds.jose.jwk.source.JWKSource;
import com.nimbusds.jose.proc.SecurityContext;
import com.ssl.app.security.filters.LoginAuthFilter;
import com.ssl.app.utility.ConsoleUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.oauth2.server.resource.OAuth2ResourceServerConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.oauth2.jwt.JwtDecoder;
import org.springframework.security.oauth2.jwt.JwtEncoder;
import org.springframework.security.oauth2.jwt.NimbusJwtDecoder;
import org.springframework.security.oauth2.jwt.NimbusJwtEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
#Configuration
//#AllArgsConstructor
#EnableWebSecurity
//#EnableConfigurationProperties
public class SecurityConfig {
private final LoginAuthFilter loginAuthFilter;
private final RsaKeyProperties rsaKeyProperties;
public SecurityConfig(LoginAuthFilter loginAuthFilter, RsaKeyProperties rsaKeyProperties) {
this.loginAuthFilter = loginAuthFilter;
this.rsaKeyProperties = rsaKeyProperties;
}
#Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http
.csrf(csrf -> csrf.disable())
.authorizeRequests(auth -> auth
.anyRequest().authenticated()
)
.oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt) // get config_class :: method
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.addFilterBefore(loginAuthFilter, UsernamePasswordAuthenticationFilter.class)
.build();
}
#Bean
JwtDecoder jwtDecoder() {
ConsoleUtil.PrintRow(this.getClass().getSimpleName(),"Decode publicKey", "true");
// Get public key and decode and return
return NimbusJwtDecoder.withPublicKey(rsaKeyProperties.publicKey()).build();
}
#Bean
JwtEncoder jwtEncoder() {
ConsoleUtil.PrintRow(this.getClass().getSimpleName(),"Encode jwt", true);
JWK jwk = new RSAKey.Builder(rsaKeyProperties.publicKey()).privateKey(rsaKeyProperties.privateKey()).build();
JWKSource<SecurityContext> jwks = new ImmutableJWKSet<>(new JWKSet(jwk));
return new NimbusJwtEncoder(jwks);
}
}
Record
import org.springframework.boot.context.properties.ConfigurationProperties;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
#ConfigurationProperties(prefix ="rsa")
public record RsaKeyProperties(RSAPublicKey publicKey, RSAPrivateKey privateKey) {
}
I tried adding #EnableConfigurationProperties, and EnableAutoConfiguration to the SecurtyConfig would work, but it has no effect. #Value annotation don't work either. The SecurityConfig required a bean, but what bean?
Maybe you should refer to this article
spring-security-jwt

Spring Security Oauth2 + OIDC (OpenID Connect) OP Initiated/Back Channel logout with Multiple RPs

An Authentication server (OP) with multiple RPs is the architecture. Please check the image below.
I was able to successfully log out with RP initiated logout which is if I log out from any of the clients the client(RP) gets logged out and the OP also gets logged out.
Please find OpenID Provider Discovery Metadata;
{
"jwks_uri":"https://<Auth Server URL>/token_keys",
"subject_types_supported":["public"],
"end_session_endpoint":"https://<Auth Server URL>/logout",
"issuer":"https://<Auth Server URL>/oauth/token",
"authorization_endpoint":"https://<Auth Server URL>/oauth/authorize",
"token_endpoint":"https://<Auth Server URL>/oauth/token"
}
with "end_session_endpoint" present in the discovery I was able to do the RP initiated logout using the following code in the clients,
import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
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.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserRequest;
import org.springframework.security.oauth2.client.oidc.web.logout.OidcClientInitiatedLogoutSuccessHandler;
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
import org.springframework.security.oauth2.client.userinfo.OAuth2UserService;
import org.springframework.security.oauth2.core.oidc.user.OidcUser;
import org.springframework.security.oauth2.core.oidc.user.OidcUserAuthority;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
import org.springframework.security.web.header.writers.StaticHeadersWriter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import com.nimbusds.jose.shaded.json.JSONArray;
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true, jsr250Enabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private ClientRegistrationRepository clientRegistrationRepository;
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/assets/**").antMatchers("/assets/bundles/**");
}
#Bean(name = "oidcUserService")
OAuth2UserService<OidcUserRequest, OidcUser> oidcUserService() {
return new CustomOidcUserService();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and().headers(headers -> headers.cacheControl().and()
.addHeaderWriter(new StaticHeadersWriter("X-UA-Compatible", "IE=edge"))
.frameOptions(frameOptions -> frameOptions.sameOrigin()).httpStrictTransportSecurity())
.authorizeRequests(authorize -> authorize
.antMatchers("/error").permitAll()
.anyRequest().authenticated())
.oauth2Login(oauthLogin -> oauthLogin
.userInfoEndpoint()
.oidcUserService(this.oidcUserService()))
.logout(logout -> logout
.logoutSuccessHandler(oidcLogoutSuccessHandler())
.invalidateHttpSession(true)
.clearAuthentication(true)
.deleteCookies("JSESSIONID","CSRF-TOKEN","XSRF-TOKEN")
.permitAll())
.csrf((csrf) -> csrf
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()));
}
private OidcClientInitiatedLogoutSuccessHandler oidcLogoutSuccessHandler() {
OidcClientInitiatedLogoutSuccessHandler oidcLogoutSuccessHandler = new OidcClientInitiatedLogoutSuccessHandler(this.clientRegistrationRepository);
oidcLogoutSuccessHandler.setPostLogoutRedirectUri("{baseUrl}");
return oidcLogoutSuccessHandler;
}
#Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("*"));
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
But I have no idea how to implement OP initiated Logot, which logs out all the clients under the OP if the OP session expires or OP gets logged out. Are there any examples available? I have been researching for this for few days and found about having another key called "check_session_iframe" but could not find proper documentation from spring. Please share if you have any examples. Thank you.
If the OP's metadata does not include a check_session_iframe frontchannel_logout_supported or backchannel_logout_supported, then it simply does not support single logout, which would trigger a logout at the clients aka "OP initiated logout".
The check_session_iframe contains an URL under the control of the OP. The client will embed this URL as an iframe, also called OP iframe. The OP iframe has access to the User Agent state at the OpenID provider (since it is the same domain). The client will create another iframe, the RP iframe, to send postMessage requests to the OP iframe for checking the session status. The OP iframe will then respond with a postMessage request to the RP iframe with the result (changed, unchanged or error).
Regarding the client part of the session management specification the only thing you have to do is to embed the OP iframe, give it an id so that you can send postMessage requests to it and handle postMessage requests from it within your RP iframe. Check out the pseudo code in the specification:
https://openid.net/specs/openid-connect-session-1_0.html#RPiframe

How to integrate spring actuator in a non spring boot application?

i have a GWT application which is not a spring boot application and i managed to integrate actuator v1.5.9 with spring v4.3.3 with this configuration class.
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.autoconfigure.EndpointAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.EndpointWebMvcManagementContextConfiguration;
import org.springframework.boot.actuate.autoconfigure.HealthIndicatorAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.ManagementServerPropertiesAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.ManagementWebSecurityAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.MetricExportAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.MetricFilterAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.MetricRepositoryAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.MetricsChannelAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.MetricsDropwizardAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.PublicMetricsAutoConfiguration;
import org.springframework.boot.actuate.endpoint.EndpointProperties;
import org.springframework.boot.actuate.endpoint.HealthEndpoint;
import org.springframework.boot.actuate.endpoint.mvc.HealthMvcEndpoint;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.PropertySource;
#Configuration
#Import({ EndpointWebMvcManagementContextConfiguration.class, ManagementServerPropertiesAutoConfiguration.class,
EndpointAutoConfiguration.class, HealthIndicatorAutoConfiguration.class, MetricExportAutoConfiguration.class,
MetricFilterAutoConfiguration.class, MetricsChannelAutoConfiguration.class,
MetricsDropwizardAutoConfiguration.class, MetricRepositoryAutoConfiguration.class,
PublicMetricsAutoConfiguration.class,EndpointProperties.class, ManagementWebSecurityAutoConfiguration.class })
#PropertySource("classpath:Application.properties")
public class HealthCheckConfiguration {
#Bean
#Autowired
public HealthMvcEndpoint healthMvcEndpoint(HealthEndpoint delegate) {
return new HealthMvcEndpoint(delegate, true);
}
}
Could you help me to do the same in spring actuator v2.3.1 and spring v5.2.7, because there are many classes not available in the new version.
Thanks,
This configuration worked for me (for a SpringMVC project with spring boot actuator)
#Configuration
#Import({
EndpointAutoConfiguration.class,
HealthIndicatorAutoConfiguration.class,
InfoEndpointAutoConfiguration.class,
HealthEndpointAutoConfiguration.class,
WebEndpointAutoConfiguration.class,
ServletManagementContextAutoConfiguration.class,
ManagementContextAutoConfiguration.class,
})
#EnableConfigurationProperties(CorsEndpointProperties.class)
class ActuatorConfiguration {
#Bean //taken from WebMvcEndpointManagementContextConfiguration.class
public WebMvcEndpointHandlerMapping webEndpointServletHandlerMapping(WebEndpointsSupplier webEndpointsSupplier,
ServletEndpointsSupplier servletEndpointsSupplier, ControllerEndpointsSupplier controllerEndpointsSupplier,
EndpointMediaTypes endpointMediaTypes, CorsEndpointProperties corsProperties,
WebEndpointProperties webEndpointProperties) {
List<ExposableEndpoint<?>> allEndpoints = new ArrayList<>();
Collection<ExposableWebEndpoint> webEndpoints = webEndpointsSupplier.getEndpoints();
allEndpoints.addAll(webEndpoints);
allEndpoints.addAll(servletEndpointsSupplier.getEndpoints());
allEndpoints.addAll(controllerEndpointsSupplier.getEndpoints());
EndpointMapping endpointMapping = new EndpointMapping(webEndpointProperties.getBasePath());
return new WebMvcEndpointHandlerMapping(endpointMapping, webEndpoints, endpointMediaTypes,
corsProperties.toCorsConfiguration(),
new EndpointLinksResolver(allEndpoints, webEndpointProperties.getBasePath()));
}
#Bean
DispatcherServletPath dispatcherServletPath() {
return () -> "/";
}
}
I did include
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator-autoconfigure</artifactId>
<version>2.1.18.RELEASE</version>
</dependency>
for compatibility with the baseline Spring version I've been using (5.1.19.RELEASE)
The actuator endpoints are exposed with /actuator/*

localhost ip stops working on https

The RESTful calls to my Spring Boot project were working fine when using the default http, with using the localhost alias as well as my localhost ip address e.g. http://localhost:8080/getCall, & http://xx.xx.xx.xx:8443/getCall.
When enabling https on the project, the calls are working fine using localhost alias, but not the localhost ip address, which gives http error 0. e.g. https://localhost:8443/getCall working, https://xx.xx.xx.xx:8443/getCall not working. Strangely when calling https://xx.xx.xx.xx:8443/getCall directly through Chrome browser, it takes me to Proceed with Caution page, and once proceeded, issue goes away entirely. Although this is a hack, and still needs to be resolved.
Here is the code used to enable https..
Inside WebSecurityConfigurerAdapter subclass, and override method; configure(HttpSecurity http):
http.requiresChannel().antMatchers("/**").requiresSecure();
Inside application.properties, in src/main/resources (where also myRecepientsCert.p12 resides created with command line tools):
server.port=8443
security.require-ssl=true
server.ssl.key-store=classpath:myRecepientsCert.p12
server.ssl.key-store-password=not-telling
server.ssl.key-store-type=PKCS12
server.ssl.key-alias=myRecepientCert
Here is full code to example project I am using..
MyRestController
package com.learnspring.SpringBootHttps;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
#RestController
#CrossOrigin("*")
public class MyRestController {
public class POJOForJSON {
public String key;
public String key2;
}
#RequestMapping(value = "/getCall", method = RequestMethod.GET, produces = "application/json")
public POJOForJSON getCall() {
POJOForJSON json = new POJOForJSON();
json.key = "value";
json.key2 = "value2";
return json;
}
#RequestMapping(value = "/postCall", method = RequestMethod.POST, produces = "application/json")
public POJOForJSON postCall() {
POJOForJSON json = new POJOForJSON();
json.key = "value";
json.key2 = "value2";
return json;
}
}
SpringBootHttpsApplication
package com.learnspring.SpringBootHttps;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class SpringBootHttpsApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootHttpsApplication.class, args);
}
}
WebSecurityConfig
import java.util.Arrays;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
#Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.cors() // allow CORS calls with #CrossOrigin annotation on restful call
.and().csrf().disable()
.authorizeRequests().antMatchers("/**").permitAll();
http.requiresChannel()
.antMatchers("/**").requiresSecure();
}
#Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
// configuration.setAllowedOrigins(Arrays.asList("http://localhost:8100"));
configuration.setAllowedOrigins(Arrays.asList("*"));
configuration.setAllowedMethods(Arrays.asList("GET","POST"));
configuration.setAllowCredentials(true);
configuration.setAllowedHeaders(Arrays.asList("Content-Type", "Access-Control-Allow-Origin", "Access-Control-Allow-Credentials", "Access-Control-Allow-Methods", "x-authorization-firebase"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
To answer the question, the self-signed certificate is doing what it's suppose to do. They are not automatically trusted, and are used for TEST/DEV environments. You need to have a publicly signed certificate for a PROD environment. To do that I am yet to find out (but I think you can get it from AWS, if you have an account).

embedded tomcat valve spring boot

I'm trying to configure the LogbackValve for getting access logs in case my Spring Boot based web application is running from embedded Tomcat. Following is the code for configuration:
import javax.servlet.Servlet;
import org.apache.catalina.startup.Tomcat;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import ch.qos.logback.access.tomcat.LogbackValve;
#Configuration
public class EmbeddedTomcatConfigurator {
#Bean
#ConditionalOnClass({ Servlet.class, Tomcat.class })
#ConditionalOnBean(value = LogbackValve.class)
public TomcatEmbeddedServletContainerFactory tomcatEmbeddedServletContainerFactory(LogbackValve logbackValve) {
TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory();
factory.addContextValves(logbackValve);
return factory;
}
#Bean
#ConditionalOnProperty(name = "embedded.tomcat.logback.access.config.path")
public LogbackValve logbackValve(#Value("${embedded.tomcat.logback.access.config.path:}") String fileName) {
LogbackValve logbackValve = new LogbackValve();
logbackValve.setFilename(fileName);
return logbackValve;
}
}
However, everytime I start the application using "mvn spring-boot:run" in debug mode, I see logs saying, "LogbackValve not found" when trying to create instance of "tomcatEmbeddedServletContainerFactory" bean. However, another log statement indicates creation of this bean. Due to this, it always initializes the bean defined in the auto-configuration class "org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration".
For now, I've modified my class as :
import javax.servlet.Servlet;
import org.apache.catalina.startup.Tomcat;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import ch.qos.logback.access.tomcat.LogbackValve;
#Configuration
public class EmbeddedTomcatConfigurator {
#Bean
#ConditionalOnClass({ Servlet.class, Tomcat.class })
#ConditionalOnProperty(name = "embedded.tomcat.logback.access.config.path")
public TomcatEmbeddedServletContainerFactory tomcatEmbeddedServletContainerFactory(#Value("${embedded.tomcat.logback.access.config.path:}") String logbackAccessPath) {
TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory();
factory.addContextValves(getLogbackValve(logbackAccessPath));
return factory;
}
private LogbackValve getLogbackValve(String fileName) {
LogbackValve logbackValve = new LogbackValve();
logbackValve.setFilename(fileName);
return logbackValve;
}
}
I've already asked this question on Git and it has been resolved. But, here, the point I'm trying to bring up is, why the #ConditionalOnBean(value = LogbackValve.class) isn't detecting the bean, which has been defined as well.

Resources