我是Spring MVC框架的新手,我遇到了一个我自己无法解决的问题。一切都是在我将spring security与我的应用程序集成后开始的,之后HTML表单中的所有unicode值都没有编码(spring security工作正常)。我得出的结论是,这可能是因为我的DelegatingFilterProxy
被称为链中的第一个过滤器。
这是我认为可以使用的配置,但它没有:
1)我正在从javadoc扩展AbstractSecurityWebApplicationInitializer:
Registers the DelegatingFilterProxy to use the springSecurityFilterChain() before any
other registered Filter.
从那个类我也覆盖了关于javadoc的SpringSecurityFilterChain方法:
Invoked before the springSecurityFilterChain is added.
所以我认为这将是注册CharacterEncodingFilter的最佳位置:
public class MessageSecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {
@Override
protected void beforeSpringSecurityFilterChain(ServletContext servletContext) {
FilterRegistration.Dynamic characterEncodingFilter = servletContext.addFilter("encodingFilter", new CharacterEncodingFilter());
characterEncodingFilter.setInitParameter("encoding", "UTF-8");
characterEncodingFilter.setInitParameter("forceEncoding", "true");
characterEncodingFilter.addMappingForUrlPatterns(null, true, "/*");
}
}
但这不起作用。
我厌倦的另一个选择是通过覆盖getServletFilters()方法在AbstractAnnotationConfigDispatcherServletInitializer类中注册过滤器:
public class WebAppInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer {
//{!begin addToRootContext}
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[] { SecurityConfig.class, DatabaseConfig.class, InternationalizationConfig.class };
}
//{!end addToRootContext}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[] { WebAppConfig.class };
}
@Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
@Override
protected Filter[] getServletFilters() {
CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
characterEncodingFilter.setEncoding("UTF-8");
characterEncodingFilter.setForceEncoding(true);
return new Filter[] { characterEncodingFilter};
}
}
但这不起作用。有没有人遇到过同样的问题,或者有一些想法如何解决这个问题?
以下是我通过AbstractSecurityWebApplicationInitializer注册编码过滤器的第一个选项的完整配置:
@Order(1)
public class MessageSecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {
@Override
protected void beforeSpringSecurityFilterChain(ServletContext servletContext) {
FilterRegistration.Dynamic characterEncodingFilter = servletContext.addFilter("encodingFilter", new CharacterEncodingFilter());
characterEncodingFilter.setInitParameter("encoding", "UTF-8");
characterEncodingFilter.setInitParameter("forceEncoding", "true");
characterEncodingFilter.addMappingForUrlPatterns(null, true, "/*");
}
}
@Order(2)
public class WebAppInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer {
//{!begin addToRootContext}
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[] { SecurityConfig.class, DatabaseConfig.class, InternationalizationConfig.class };
}
//{!end addToRootContext}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[] { WebAppConfig.class };
}
@Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
}
@EnableWebMvc
//@Import(value = {DatabaseConfig.class, InternationalizationConfig.class, SecurityConfig.class})
@ComponentScan(basePackages = {"com.ajurasz.controller", "com.ajurasz.service", "com.ajurasz.model"})
@Configuration
public class WebAppConfig extends WebMvcConfigurerAdapter {
@Bean
public UrlBasedViewResolver viewResolver() {
UrlBasedViewResolver urlBasedViewResolver = new UrlBasedViewResolver();
urlBasedViewResolver.setViewClass(TilesView.class);
urlBasedViewResolver.setContentType("text/html;charset=UTF-8");
return urlBasedViewResolver;
}
@Bean
public TilesConfigurer tilesConfigurer() {
TilesConfigurer tilesConfigurer = new TilesConfigurer();
tilesConfigurer.setDefinitions(new String[] {"/WEB-INF/tiles.xml"});
return tilesConfigurer;
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/**");
registry.addResourceHandler("/documents/**").addResourceLocations("/WEB-INF/pdfs/documents/**");
}
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
PageableHandlerMethodArgumentResolver pageableHandlerMethodArgumentResolver =
new PageableHandlerMethodArgumentResolver();
pageableHandlerMethodArgumentResolver.setFallbackPageable(new PageRequest(0, 4, new Sort(Sort.Direction.DESC, "id")));
argumentResolvers.add(pageableHandlerMethodArgumentResolver);
}
}
依赖关系:
spring-mvc 3.2.5.RELEASE
spring-security-config,spring-security-web,spring-security-core 3.2.0.RELEASE
我正在以下链接中进行此操作: https://github.com/ajurasz/Manager
答案 0 :(得分:57)
我们需要在第一次读取请求属性的过滤器之前添加CharacterEncodingFilter。有securityFilterChain(排在第二位。在公制过滤器之后),我们可以在其中添加我们的过滤器。读取属性的第一个过滤器(内部安全链)是CsrfFilter,因此我们将CharacterEncodingFilter放在它之前。
简短的解决方案是:
@Configuration
@EnableWebMvcSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
CharacterEncodingFilter filter = new CharacterEncodingFilter();
filter.setEncoding("UTF-8");
filter.setForceEncoding(true);
http.addFilterBefore(filter,CsrfFilter.class);
//rest of your code
}
//rest of your code
}
答案 1 :(得分:17)
我最近遇到了同样的问题,你的第一次尝试实际上非常接近我最终使用的解决方案(这里是你的代码,已修复):
public class MessageSecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {
@Override
protected void beforeSpringSecurityFilterChain(ServletContext servletContext) {
FilterRegistration.Dynamic characterEncodingFilter = servletContext.addFilter("encodingFilter", new CharacterEncodingFilter());
characterEncodingFilter.setInitParameter("encoding", "UTF-8");
characterEncodingFilter.setInitParameter("forceEncoding", "true");
characterEncodingFilter.addMappingForUrlPatterns(null, false, "/*");
}
}
唯一的区别是为url模式添加过滤器映射时的第二个参数。此参数的Javadoc表示:
isMatchAfter - 如果给定的过滤器映射应该在任何声明的过滤器映射之后匹配,则为true;如果在获得此FilterRegistration的ServletContext的任何已声明的过滤器映射之前应该匹配,则为false
因此将其设置为false应该干净地解决您的问题(不涉及任何XML)。
答案 2 :(得分:13)
我不知道究竟是什么问题但我永远不会在Spring中配置这么简单的过滤器。而是在web.xml
中正确地做 - 更容易开发,理解和调试。
<!-- Hint: http://wiki.apache.org/tomcat/FAQ/CharacterEncoding#Q8 -->
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
重要说明:在 Spring Security过滤器链之前(即DelegatingFilterProxy
的过滤器映射之前)配置此过滤器的映射。
答案 3 :(得分:11)
有同样的问题。我的解决方案是使用原始servlet过滤器:
public void onStartup(ServletContext servletContext) throws ServletException {
FilterRegistration.Dynamic encodingFilter = servletContext.addFilter("encoding-filter", new CharacterEncodingFilter());
encodingFilter.setInitParameter("encoding", "UTF-8");
encodingFilter.setInitParameter("forceEncoding", "true");
encodingFilter.addMappingForUrlPatterns(null, true, "/*");
}
请注意,此问题仅适用于Tomcat,但不适用于Jetty。
答案 4 :(得分:3)
我用过
@Configuration
@EnableWebMvcSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
CharacterEncodingFilter filter = new CharacterEncodingFilter();
filter.setEncoding("UTF-8");
filter.setForceEncoding(true);
http.addFilterBefore(filter,CsrfFilter.class);
//rest of your code
}
//rest of your code
}
答案 5 :(得分:2)
我不喜欢到目前为止发布的答案,因为要么使用模糊的Spring类,要么依赖于实现细节。
在我看来,事情应该只需定义一个标准@Bean
高@Order
,所以这是Boot的错 - 但幸运的是,如果我们使用的话,一切都按预期工作(?) FilterRegistrationBean
代替普通Filter
(我使用Boot 1.1.5):
@Bean
public FilterRegistrationBean filterRegistrationBean() {
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
registrationBean.setFilter(characterEncodingFilter);
characterEncodingFilter.setEncoding("UTF-8");
characterEncodingFilter.setForceEncoding(true);
registrationBean.setOrder(Integer.MIN_VALUE);
registrationBean.addUrlPatterns("/*");
return registrationBean;
}