【问题标题】:Spring Boot: Filter execution threw an exception - java.lang.AbstractMethodErrorSpring Boot:过滤器执行引发异常 - java.lang.AbstractMethodError
【发布时间】:2015-11-15 12:41:51
【问题描述】:

我使用 Spring Boot 设置了一个相当简单的安全应用程序,但在成功登录后,我不断从服务器收到此异常:

javax.servlet.ServletException: Filter execution threw an exception
org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:85)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
org.springframework.boot.context.web.ErrorPageFilter.doFilter(ErrorPageFilter.java:116)
org.springframework.boot.context.web.ErrorPageFilter.access$000(ErrorPageFilter.java:60)
org.springframework.boot.context.web.ErrorPageFilter$1.doFilterInternal(ErrorPageFilter.java:91)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
org.springframework.boot.context.web.ErrorPageFilter.doFilter(ErrorPageFilter.java:109)

root cause

java.lang.AbstractMethodError
    javax.servlet.http.HttpServletRequestWrapper.changeSessionId(HttpServletRequestWrapper.java:290)
    javax.servlet.http.HttpServletRequestWrapper.changeSessionId(HttpServletRequestWrapper.java:290)
    sun.reflect.GeneratedMethodAccessor295.invoke(Unknown Source)
    sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    java.lang.reflect.Method.invoke(Method.java:497)
    org.springframework.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:203)
    org.springframework.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:188)
    org.springframework.security.web.authentication.session.ChangeSessionIdAuthenticationStrategy.applySessionFixation(ChangeSessionIdAuthenticationStrategy.java:48)
    org.springframework.security.web.authentication.session.AbstractSessionFixationProtectionStrategy.onAuthentication(AbstractSessionFixationProtectionStrategy.java:82)
    org.springframework.security.web.authentication.session.ChangeSessionIdAuthenticationStrategy.onAuthentication(ChangeSessionIdAuthenticationStrategy.java:32)
    org.springframework.security.web.authentication.session.CompositeSessionAuthenticationStrategy.onAuthentication(CompositeSessionAuthenticationStrategy.java:83)
    org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:216)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:110)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:105)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
    org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
    org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:85)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    org.springframework.boot.context.web.ErrorPageFilter.doFilter(ErrorPageFilter.java:116)
    org.springframework.boot.context.web.ErrorPageFilter.access$000(ErrorPageFilter.java:60)
    org.springframework.boot.context.web.ErrorPageFilter$1.doFilterInternal(ErrorPageFilter.java:91)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    org.springframework.boot.context.web.ErrorPageFilter.doFilter(ErrorPageFilter.java:109)

这是我的初始化类:

@EnableAutoConfiguration
@SpringBootApplication
public class RecruitingDashboardApplication extends SpringBootServletInitializer {

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

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


}

还有我的viewResolver配置类:

@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {

    @Bean 
    public ViewResolver viewResolver() {
        ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();
        templateResolver.setPrefix("templates/");
        templateResolver.setSuffix(".html");

        SpringTemplateEngine engine = new SpringTemplateEngine();
        engine.setTemplateResolver(templateResolver);

        ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
        viewResolver.setTemplateEngine(engine);
        return viewResolver;
    }


    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/").setViewName("dashboard");
        registry.addViewController("/login").setViewName("login");
    }

}

最后是我的安全配置类:

@Configuration
@EnableWebMvcSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.headers()
                .frameOptions()
                .disable()
            .authorizeRequests()
                .antMatchers("/css/**", "/img/**", "/fonts/**").permitAll()
                .anyRequest()
                .authenticated()
                .and()
            .formLogin()
                .loginPage("/login")
                .permitAll()
                .and()
            .logout()
                .permitAll();
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth
            .inMemoryAuthentication()
                .withUser("username").password("password").roles("USER");
    }

}

这些是我正在使用的 pom 依赖项:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <exclusions>
            <exclusion>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-tomcat</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
        <scope>provided</scope>
    </dependency>

    <dependency>
        <groupId>net.sourceforge.nekohtml</groupId>
        <artifactId>nekohtml</artifactId>
        <version>1.9.22</version>
    </dependency>

</dependencies>

感谢任何帮助。我在这个问题上花了三天时间,在网上到处搜索,但找不到解决方案。

更新

部署到 Tomcat 8 时似乎没有出现异常。我只在 Tomcat 7 上得到它。

更新 2

我更新了我的 pom 文件以包含 spring-boot-starter-tomcat 依赖项和 providedscope。如in this question 所述,我还从spring-boot-starter-web 中排除了相同的瞬态依赖。但是,问题仍然存在。

【问题讨论】:

  • 看起来依赖版本错误。 changeSessionId 方法在 Servlet API 3.1 中定义,您的类路径中可能有 3.0.1。
  • 听起来不错。但是如果所有的spring boot starter依赖都捆绑了怎么改呢?
  • 另外,3.1 版不是仅在 Tomcat 8 上可用吗?我的属性上有&lt;tomcat.version&gt;7.0.63&lt;/tomcat.version&gt;,我认为这会处理获得正确的依赖关系。

标签: java spring maven spring-security spring-boot


【解决方案1】:

您正在部署基于战争的工件。 spring-boot-starter-web 提供了一个嵌入式 Web 容器(默认为 Tomcat),servlet-api 显然与之配套。您部署战争的容器使用另一个版本的 API。

你需要用提供的范围标记spring-boot-starter-tomcat,这样你的战争就不会带来额外的依赖。 Spring Boot maven 插件能够检测到这一点,并将这些提供的依赖项放置在 fat war 的单独位置,以便您仍然可以从命令行运行它 (java -jar yourapp.war)。您可以不使用它并只是构建一个常规的战争文件。在这种情况下不要使用 Spring Boot maven 插件。

这是解释in the documentation

【讨论】:

  • 感谢您的回答。我已经进行了您提出的更改(请参阅问题更新),但问题仍然存在。
  • 我能说什么?本质上是相同的问题,servlet-api 是您项目的另一个依赖项的提供者。运行mvn dependency:tree 看看谁是罪魁祸首。您也可以快速查看WEB-INF/lib 并确保其中没有与servlet 相关的jar。
  • 查看this question 上的评论后,我从tomcat/lib 文件夹中删除了servlet-api。我相信这种情况下的答案是您建议对 pom.xml 文件的更改和清理 tomcat/lib 文件夹的组合。
  • 一点也不!你不应该弄乱你的tomcat/lib,因为这是服务器必须使用的原始 jar。就像我说的那样,你的战争中必须有 servlet-api(可能是阴影或不同的名称)。这就是导致问题的原因。
  • 我检查了我的war文件,WEB-INF/lib中没有servlet-api。我还跑了mvn dependency:tree,但没有透露任何信息。如果它使用不同的名称,我不知道我还能如何弄清楚它在哪里。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-01
  • 1970-01-01
  • 2018-11-01
相关资源
最近更新 更多