CharacterEncodingFilter не работает вместе с Spring Security 3.2.0
Я новичок в Spring MVC framework, и у меня есть проблема, которую я не могу решить самостоятельно. Все началось, когда я интегрировал spring security с моим приложением, после чего все значения unicode из HTML-формы не были закодированы (spring security работает правильно). Я пришел к выводу, что это происходит, вероятно, потому, что мой DelegatingFilterProxy
вызывается как первый фильтр в цепочке.
вот моя конфигурация, что я думал будет работать, но это не так:
1)я расширение AbstractSecurityWebApplicationInitializer-из javadoc:
Registers the DelegatingFilterProxy to use the springSecurityFilterChain() before any
other registered Filter.
из этого класса я также переопределяю метод beforeSpringSecurityFilterChain, который касается javadoc:
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, "/*");
}
}
но это не работает.
другой вариант, который я устал, - зарегистрировать фильтр через класс AbstractAnnotationConfigDispatcherservletinitializer путем переопределения getServletFilters() метод:
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);
}
}
зависимости:
весна-mvc 3.2.5.Отпустите
spring-security-config, spring-security-web, spring-security-core 3.2.0.Отпустите
Я работаю над этим по следующей ссылке: https://github.com/ajurasz/Manager
6 ответов
та же проблема. Моим решением было использовать необработанный фильтр сервлетов:
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.
нужно добавить 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
}
недавно я столкнулся с той же проблемой, и ваша первая попытка на самом деле очень близка к решению, которое я использовал (вот ваш код, исправлено) :
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. The Javadoc для этого параметра указано :
isMatchAfter-true, если заданное отображение фильтра должно быть сопоставлено после любых объявленных отображений фильтра, и false, если оно должно быть сопоставлено до любые объявленные сопоставления фильтров ServletContext, из которого была получена эта FilterRegistration
поэтому установка его в false должна чисто решить вашу проблему (без участия XML).
Я не знаю что точно проблема в том, но я бы никогда не настроил такой простой фильтр внутри 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>
важно: настройте отображение этого фильтра до цепь фильтра безопасности весны (т. е. перед отображением фильтра для DelegatingFilterProxy
).
я использовал
@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
}
мне не нравятся ответы, опубликованные до сих пор, потому что либо используют неясные классы Spring, либо полагаются на детали реализации.
на мой взгляд все должно работать, просто определив стандартный @Bean
высокого @Order
, Так что это ошибка загрузки, но, к счастью, все работает, как ожидалось (?) если мы используем 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;
}