将我的Spring框架从4.3.13稍微升级到4.3.14并将spring-security 4.2.3升级到4.2.4后,我的Web应用程序无法初始化(Tomcat 8.5.23,JDK 1.8。 0_152),出现以下错误:
[DEBUG] Retrieved dependent beans for bean 'springSecurityFilterChain': [webSecurityExpressionHandler]
[WARN] Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'springSecurityFilterChain' defined in org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration:
Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.servlet.Filter]: Factory method 'springSecurityFilterChain' threw exception; nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'mvcHandlerMappingIntrospector' available: A Bean named mvcHandlerMappingIntrospector of type org.springframework.web.servlet.handler.HandlerMappingIntrospector is required to use MvcRequestMatcher.
Please ensure Spring Security & Spring MVC are configured in a shared ApplicationContext.
抛出此异常的类是CorsConfigurer.MvcCorsFilter,它是spring-security
的一部分。
我在这个错误(SPR-16301)上找到了一个有用的线程,它解释了这个异常是在新版本的Spring(5.0.3和4.3.14,{{{ {3}}在同一天)。
我的WebConfig
类具有@EnableWebSecurity
注释,如上面的主题中所述,导入DelegatingWebMvcConfiguration
,它声明了released。
本质上,该线程表明已声明了多个上下文(根上下文和子上下文),并且我可能已在多个上下文中启用了Spring Security。
但是,在我的案例中,我没有看到解决方案。我有重复/重叠注释吗?我是否在WebInitializer
课程中错误地加载了Root和Security配置?
我的Spring配置类列在下面(我的AuthenticationProvider
除外)。
WebInitializer.java
package com.x.spring;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
public final class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer
{
@Override
protected Class<?>[] getRootConfigClasses()
{
return new Class<?>[] {RootConfig.class, WebSecurityConfig.class};
}
@Override
protected Class<?>[] getServletConfigClasses()
{
return new Class<?>[] {WebConfig.class};
}
@Override
protected String[] getServletMappings()
{
return new String[] {"/"};
}
@Override
protected DispatcherServlet createDispatcherServlet(final WebApplicationContext servletAppContext)
{
final DispatcherServlet dispatcherServlet = (DispatcherServlet) super.createDispatcherServlet(servletAppContext);
dispatcherServlet.setThrowExceptionIfNoHandlerFound(true);
return dispatcherServlet;
}
}
RootConfig.java
package com.x.spring;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
@Configuration
@ComponentScan(basePackages = {"com.x.spring.controller"}, excludeFilters = {@Filter(type = FilterType.ANNOTATION, value = EnableWebMvc.class)})
public class RootConfig
{
}
WebConfig.java
package com.x.spring;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.tiles3.TilesConfigurer;
import org.springframework.web.servlet.view.tiles3.TilesViewResolver;
@Configuration
@EnableWebMvc
@ComponentScan("com.x.spring.controller")
public class WebConfig extends WebMvcConfigurerAdapter
{
@Bean
public ViewResolver viewResolver()
{
final TilesViewResolver resolver = new TilesViewResolver();
return resolver;
}
@Bean
public TilesConfigurer tilesConfigurer()
{
final TilesConfigurer tiles = new TilesConfigurer();
tiles.setDefinitions(new String[] {"/WEB-INF/tiles.xml"});
tiles.setCheckRefresh(true);
return tiles;
}
@Bean
public CommonsMultipartResolver multipartResolver()
{
final CommonsMultipartResolver resolver = new CommonsMultipartResolver();
resolver.setMaxUploadSize(10000000);
return resolver;
}
// These methods enable '.' in RequestMappings.
@Override
public final void configurePathMatch(final PathMatchConfigurer configurer)
{
configurer.setUseRegisteredSuffixPatternMatch(true);
return;
}
@Override
public final void addResourceHandlers(final ResourceHandlerRegistry registry)
{
registry.addResourceHandler("/css/**").addResourceLocations("/css/");
registry.addResourceHandler("/js/**").addResourceLocations("/js/");
registry.addResourceHandler("/images/**").addResourceLocations("/images/");
return;
}
@Override
public void addCorsMappings(final CorsRegistry registry)
{
registry.addMapping("/**");
return;
}
}
WebSecurityConfig.java
package com.x.spring;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
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 com.x.spring.security.XAuthenticationProvider;
/**
* Spring web security configuration.
* This class must be registered with WebInitializer.
*/
@Configuration
@EnableWebSecurity
@ComponentScan("com.x.spring.security")
public class WebSecurityConfig extends WebSecurityConfigurerAdapter
{
@Autowired
private XAuthenticationProvider authenticationProvider;
/**
* https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/
*/
public WebSecurityConfig()
{
super();
return;
}
@Override
public void configure(final WebSecurity web) throws Exception
{
super.configure(web);
return;
}
@Override
protected void configure(final HttpSecurity http) throws Exception
{
http
.csrf().disable()
.cors()
.and().headers().frameOptions().sameOrigin()
.and()
.authorizeRequests()
.antMatchers("/my-account").hasAuthority("USER")
.anyRequest().permitAll()
.and().httpBasic().realmName("X")
.and().formLogin().loginPage("/login")
.and().logout().logoutSuccessUrl("/")
.and().rememberMe().key("XSecured")
;
return;
}
@Override
protected void configure(final AuthenticationManagerBuilder auth) throws Exception
{
auth.authenticationProvider(this.authenticationProvider);
return;
}
}
WebSecurityInitializer.java
package com.x.spring;
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
/**
* This class is discovered by Spring and registers the DelegatingFilterProxy with the web container.
* It will intercept requests coming into the application and delegate them to a bean whose ID is springSecurityFilterChain.
*/
public final class WebSecurityInitializer extends AbstractSecurityWebApplicationInitializer
{
}
答案 0 :(得分:2)
初始化错误是由重复的上下文引起的。具体来说,RootConfig
类与WebConfig
类是多余的。通过删除RootConfig
并更改WebInitializer.getRootConfigClasses()
以返回WebConfig
而不是RootConfig
和WebInitializer.getServletConfigClasses()
来返回null
来解决此问题。
我的工作WebInitializer
课程如下。除了删除RootConfig
之外,其他类不需要进行任何更改。
<强> WebInitializer.java 强>
package com.x.spring;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
public final class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer
{
@Override
protected Class<?>[] getRootConfigClasses()
{
return new Class<?>[] {WebConfig.class, WebSecurityConfig.class};
}
@Override
protected Class<?>[] getServletConfigClasses()
{
return null;
}
@Override
protected String[] getServletMappings()
{
return new String[] {"/"};
}
@Override
protected DispatcherServlet createDispatcherServlet(final WebApplicationContext servletAppContext)
{
final DispatcherServlet dispatcherServlet = (DispatcherServlet) super.createDispatcherServlet(servletAppContext);
dispatcherServlet.setThrowExceptionIfNoHandlerFound(true);
return dispatcherServlet;
}