spring-boot, spring-security and dropwizard metrics

931 Views Asked by At

I have a spring-boot application with spring-security and dropwizard metrics. It uses Angularjs as a frontend. Authentication is done using separate login.html page with angularjs controller posting credentials to '/login' and after seccessful response routing to index.html (separate angularjs app). This all works quite well until I try to access dropwizard metrics. In this case I get a spring-security exception saying that user is anonymous (all other urls work fine).

My spring-security config:

@Configuration
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
@EnableWebSecurity
public class FormLoginSecurityConfigurer extends WebSecurityConfigurerAdapter {

    private class AuthSuccessHandler implements AuthenticationSuccessHandler {
        @Override
        public void onAuthenticationSuccess(HttpServletRequest request,
                HttpServletResponse response, Authentication authentication)
                throws IOException, ServletException {
            response.setStatus(HttpServletResponse.SC_OK);
        }
    }

    private class AuthFailureHandler implements AuthenticationFailureHandler {
        @Override
        public void onAuthenticationFailure(HttpServletRequest request,
                HttpServletResponse response, AuthenticationException exception)
                throws IOException, ServletException {
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        }
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/login.html", "/scripts/login/**", "/libs/**", "/styles/**", "/images/**").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin().loginPage("/login.html").loginProcessingUrl("/login")
                    .usernameParameter("username").passwordParameter("password")
                    .successHandler(new AuthSuccessHandler())
                    .failureHandler(new AuthFailureHandler())
                .and().logout().logoutUrl("/logout").logoutSuccessUrl("/login.html")
                .and().addFilterAfter(new CsrfHeaderFilter(), CsrfFilter.class)
                .csrf().csrfTokenRepository(CsrfHeaderFilter.csrfTokenRepository());
    }

    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().withUser("user").password("password").roles("USER");
    }
}

The metrics servlet is registered in the ServletContextInitilizer:

/**
 * Configuration of web application with Servlet 3.0 APIs.
 */
@Configuration
public class WebConfigurer implements ServletContextInitializer {

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        initMetrics(servletContext,
                EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.ASYNC));
    }

    /**
     * Initializes Metrics.
     */
    private void initMetrics(ServletContext servletContext, EnumSet<DispatcherType> disps) {
        log.debug("Initializing Metrics registries");
        servletContext.setAttribute(InstrumentedFilter.REGISTRY_ATTRIBUTE,
                metricRegistry);
        servletContext.setAttribute(MetricsServlet.METRICS_REGISTRY,
                metricRegistry);

        log.debug("Registering Metrics Filter");
        FilterRegistration.Dynamic metricsFilter = servletContext.addFilter("webappMetricsFilter",
                new InstrumentedFilter());

        metricsFilter.addMappingForUrlPatterns(disps, true, "/*");
        metricsFilter.setAsyncSupported(true);

        log.debug("Registering Metrics Servlet");
        ServletRegistration.Dynamic metricsAdminServlet =
                servletContext.addServlet("metricsServlet", new MetricsServlet());

        metricsAdminServlet.addMapping("/metrics/metrics/*");
        metricsAdminServlet.setAsyncSupported(true);
        metricsAdminServlet.setLoadOnStartup(2);
    }
}

However when I access anything under /metrics/metrics the browser prompts for basic authentication. The response has the following header WWW-Authenticate:"Basic realm="Spring"". Other resources are downloaded fine.

I'm new to this kind of applications and getting a bit frustrated :) Any help is appreciated.

1

There are 1 best solutions below

0
On BEST ANSWER

Seems its all in the docs if one knows what to look for - link

The Actuator security features can be modified using external properties (management.security.*). To override the application access rules add a @Bean of type WebSecurityConfigurerAdapter and use @Order(SecurityProperties.ACCESS_OVERRIDE_ORDER) if you don’t want to override the actuator access rules, or @Order(ManagementServerProperties.ACCESS_OVERRIDE_ORDER) if you do want to override the actuator access rules.

Changed the order to ManagementServerProperties.ACCESS_OVERRIDE_ORDER and now it works.