spring-guides / gs-securing-web

Securing a Web Application :: Learn how to protect your web application with Spring Security.
http://spring.io/guides/gs/securing-web/
Apache License 2.0
364 stars 447 forks source link

gs-securing-web can't be converted to a WAR using Maven #17

Closed thomasturrell closed 10 years ago

thomasturrell commented 10 years ago

Hi

When I follow the guide 'Converting a Spring Boot JAR Application to a WAR using Maven' (http://spring.io/guides/gs/convert-jar-to-war-maven/) to convert gs-securing-web to a WAR file for deployment to an external application server I get the following error when I try to access secured pages:

java.lang.IllegalArgumentException: No matching constant for [0]
    at org.springframework.http.HttpStatus.valueOf(HttpStatus.java:467)
    at org.springframework.boot.actuate.autoconfigure.MetricFilterAutoConfiguration$MetricsFilter.doFilterInternal(MetricFilterAutoConfiguration.java:99)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.springframework.boot.context.web.ErrorPageFilter.doFilter(ErrorPageFilter.java:108)
    at org.springframework.boot.context.web.ErrorPageFilter.access$000(ErrorPageFilter.java:58)
    at org.springframework.boot.context.web.ErrorPageFilter$1.doFilterInternal(ErrorPageFilter.java:87)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.boot.context.web.ErrorPageFilter.doFilter(ErrorPageFilter.java:100)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1070)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:611)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:316)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:745)

This is a bit of a show stopper as it means I can't deploy any spring boot project that uses spring security to a production server.

dsyer commented 10 years ago

It looks like a bug in Spring Boot, but it should be really hard to trip. What are the steps to repeat, please?

thomasturrell commented 10 years ago

Hi thank you for looking at this for me.

I think I have tracked it down to spring-boot-starter-actuator in the POM with spring-boot-starter-security also in the POM when the POM packaging is set to war. All though I am at a loss to explain why it would be an issue.

My POM looks like:

<?xml version="1.0" encoding="UTF-8"?>

4.0.0 ``` org.springframework gs-securing-web 0.1.0 war org.springframework.boot spring-boot-starter-parent 1.1.5.RELEASE org.springframework.boot spring-boot-starter-thymeleaf org.springframework.boot spring-boot-starter-security org.springframework.boot spring-boot-starter-tomcat provided org.springframework.boot spring-boot-starter-actuator hello.Application maven-compiler-plugin 2.3.2 org.springframework.boot spring-boot-maven-plugin spring-releases Spring Releases http://repo.spring.io/libs-release spring-releases Spring Releases http://repo.spring.io/libs-release ```

Note the inclusion of war and spring-boot-starter-actuator

I have modified WebSecurityConfig inline with https://github.com/dsyer/gs-securing-web/commit/134efa3345e4839852aa8950782aa74976959498#diff-e145d2dcdffe878840b80169748b5e09R24

package hello;

import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.authentication.configurers.GlobalAuthenticationConfigurerAdapter; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity;

@Configuration @EnableWebMvcSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception {

    http
    .authorizeRequests()
        .antMatchers("/", "/home").permitAll()
        .anyRequest().authenticated();
http
    .formLogin()
        .loginPage("/login")
        .permitAll()
        .and()
    .logout()
        .permitAll();
}

@Configuration
protected static class AuthenticationConfiguration extends
GlobalAuthenticationConfigurerAdapter {

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

}

}

I have also included the following class as per the guide 'Converting a Spring Boot JAR Application to a WAR using Maven'

package hello;

import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.context.web.SpringBootServletInitializer;

public class WebInitializer extends SpringBootServletInitializer {

@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
    return application.sources(Application.class);
}

}

When I run the resulting war file in tomcat I get the aforementioned 'HTTP Status 500 - No matching constant for [0]' error when trying to access any secured page such as http://localhost:8080/gs-securing-web/hello.

The solution seems to be to remove spring-boot-starter-actuator but since I am deploying on Elastic Beanstalk I liked the /health endpoint that actuator gives me.

dsyer commented 10 years ago

If you like the Actuator, there's no reason to remove it, if you use one of the workarounds in the issue you referenced. Namely: 1) add @EnableGlobalMethodSecurity, 2) move the authentication manager declaration out to a GlocalAuthenticationConfigurerAdapter (init method), 3) downgrade to Boot 1.1.4.RELEASE, 4) Upgrade to Boot 1.1.6.BUILD-SNAPSHOT.

thomasturrell commented 10 years ago

Thank you, downgrading seems to allow me to run actuator with security and deploy as a war. I didn't check 1.1.6.

thomasturrell commented 10 years ago

Hi Sorry to be a pain could you indulge me? Can you check out https://github.com/tommyturrell/gs-securing-web/tree/master/complete I still can't get Actuator to work with either 1.1.5 or 1.1.6 when using Security and packaging as a WAR file. If I remove Actuator everything works, if I drop down to version 1.1.4 it also works.

A comparison of my changes can be found at https://github.com/tommyturrell/gs-securing-web/compare/spring-guides:master...master

Every time I open http://localhost:8080/gs-securing-web/hello I get a HTTP Status 500 - No matching constant for [0] error.

It might just be me or my environment but I think it's a bug.

dsyer commented 10 years ago

That's an unrelated problem (https://github.com/spring-projects/spring-boot/issues/1369), and only when you deploy a WAR. Should be fixed now (and it didn't happen in 1.1.4, but the response codes in the metrics filter are not accurate there).