Tomcat + Spring - kodowanie UTF-8

0

Korzystam z:

  • Tomcata 8.14
  • Springa 4.1.1.RELEASE
  • Thymeleaf 2.1.3.RELEASE

Po wyslaniu formularza metoda POST psuje mi sie kodowanie. Probowalem to naprawić w następujący sposób.

  1. W pliku web.xml dodałem
<filter>
        <filter-name>encodingFilter</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>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
  1. W konfiguracji Tomcata w pliku server.xml mam ustawione
<Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" 
	       URIEncoding="UTF-8"/>
  1. W pliku web.xml (konfiguracja serwera Tomcat) odkomentowalem
<filter>
        <filter-name>setCharacterEncodingFilter</filter-name>
        <filter-class>org.apache.catalina.filters.SetCharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <async-supported>true</async-supported>
    </filter>
  1. Fragment konfiguracji MVC
@Bean
    public ServletContextTemplateResolver templateResolver() {
        ServletContextTemplateResolver resolver = new ServletContextTemplateResolver();
        resolver.setPrefix("/WEB-INF/views/");
        resolver.setSuffix(".html");
        // NB, selecting HTML5 as the template mode.
        resolver.setTemplateMode("HTML5");
        resolver.setCacheable(this.templateResolverCacheable);
        resolver.setCacheablePatterns(null);
        resolver.setNonCacheablePatterns(null);
        resolver.setCacheTTLMs(this.templateResolverCacheTTLMs);
        resolver.setCharacterEncoding("utf-8");
        return resolver;
    }    

    @Bean
    public ViewResolver viewResolver() {
        ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
        viewResolver.setTemplateEngine(templateEngine());
        viewResolver.setOrder(1);
        viewResolver.setViewNames(new String[]{"*"});
        viewResolver.setCache(this.viewResolverCache);
        viewResolver.setCacheLimit(this.viewResolverCacheLimit);
        viewResolver.setCacheUnresolved(this.viewResolverCacheUnresolved);
        viewResolver.setCharacterEncoding("utf-8");

        return viewResolver;
    }

Niestety nic nie pomoglo. Jakies pomysly?

0

https://github.com/Pharisaeus/SpringScaffoldApplication sklonuj to i zobacz czy ci działa kodowanie z takimi ustawieniami jak tam są :)

0

Działa :) Tylko jeszcze nie wiem dlaczego :) Skopiowalem web.xml (fragment) z tego projektu do swojego projektu i bez efektu :) W sumie to nawet podobny :)

0

A popatrz na konfiguracje thymeleaf u ciebie, konkretnie encoding dla view resolvera -> <property name="contentType" value="text/html;charset=UTF-8"/>

0

No wlasnie zerknalem na Twoj plik spring-context.xml i do takich samych wnioskow doszedlem, ze warto byloby ustawic content type. Tylko, ze jak zmodyfikowalem kod do postaci:

@Bean
    public ViewResolver viewResolver() {
        ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
        viewResolver.setTemplateEngine(templateEngine());
        viewResolver.setOrder(1);
        viewResolver.setViewNames(new String[]{"*"});
        viewResolver.setCache(this.viewResolverCache);
        viewResolver.setCacheLimit(this.viewResolverCacheLimit);
        viewResolver.setCacheUnresolved(this.viewResolverCacheUnresolved);
        viewResolver.setCharacterEncoding("utf-8");
        viewResolver.setContentType("text/html;charset=UTF-8");

        return viewResolver;
    }

To dalej mam to samo.

0

A może kodowanie w formularzu? Bo ja tam ustawiam jeszcze
<#ftl encoding='UTF-8'> w samym pliku widoku ;]

0

Probowalem dopisac do formularza atrybut accept-charset="UTF-8" i nie zadziałało :)

Natomiast wpadlem przez przypadek na dosc ciekawe zjawisko. W konfiguracji Spring Security wyłączyłem CSRF i wszystko zaczeło działać jak należy - restartowałem serwer kilka razy i za każdym razem kodowanie działało poprawnie. Natomiast po włączeniu z powrotem CSRF znowu kodowanie zaczęło się psuć - również dla pewności restartowałem serwer kilka razy.

Wypadałoby to teraz tak zrobić zeby kodowanie działało poprawnie z włączonym CSRF - jak masz jakieś pomysły to chętnie poczytam.

0

A na przykład dodanie w formularzu <form accept-charset="UTF-8" ? ;]

4

O tym pisalem w poprzednim poscie :) Dodanie atrybutu accept-charset nie pomoglo, ale problem udalo mi sie rozwiazac :)

PRAWDOPODOBNA PRZYCZYNA PROBLEMU

O ile mi wiadomo spring security dodaje sobie wlasne filtry i wyglada na to, ze dodawal je przed filterem CharacterEncodingFilter. Dlatego wlasnie majstrowanie z ustawieniami scpring security rozwiazywalo problem. Tak mi sie przynajmniej wydaje.

ROZWIAZANIE PROBLEMU

Na poczatku probowalem w swojej klasie ApplicationInitializer (dziedziczy po AbstractAnnotationConfigDispatcherServletInitializer) przeciazyc metode onStartup i w tej metodzie dodac filtr CharacterEncodingFilter - niestety nie pomoglo.

Idac dalej tym tropem postanowilem przyjrzec sie mojej klasie ApplicationSecurityInitializer, ktora dziedziczy po AbstractSecurityWebApplicationInitializer. Przeciazylem metode beforeSpringSecurityFilterChain i dodalem odpowiedni kod. Klasa ApplicationSecurityInitializer wyglada tak:

public class ApplicationSecurityInitializer extends AbstractSecurityWebApplicationInitializer {
    @Override
    protected void beforeSpringSecurityFilterChain(ServletContext servletContext) {
        super.beforeSpringSecurityFilterChain(servletContext);

        FilterRegistration.Dynamic characterEncodingFilter;
        characterEncodingFilter = servletContext.addFilter("encodingFilter",
                new CharacterEncodingFilter());
        characterEncodingFilter.setInitParameter("encoding", "UTF-8");
        characterEncodingFilter.setInitParameter("forceEncoding", "true");
        characterEncodingFilter.addMappingForUrlPatterns(null, false, "/*");
    }
}

Dodatkowo usunalem filtr z pliku web.xml i teraz kodowanie dziala poprawnie :)

1

Pewnie odkopię i dostanę złotą łopatę ale mega mi pomogłeś. Miałem ten sam problem. Dzięki! :)

2

@czarq92: nie oznaczalem adnotacja @Configuration, ale mam u siebie jeszcze klasy:

  1. SecurityConfig, ktora dziedziczy po WebSecurityConfigurerAdapter. Oznaczona jest adnotacja @Configuration i @EnableWebSecurity

  2. SecurityMethodConfig, ktora dziedziczy po GlobalMethodSecurityConfiguration oznaczona jest adnotacja @Configuration i @EnableGlobalMethodSecurity

Być może powyższe klasy konfiguracyjne wymuszają uruchomienie kodu w klasie ApplicationSecurityInitializer.

0

Również napotkałem podobny problem - polskie znaki wklepane w formularz zmieniały się do jakiejś dziwnej postaci, mimo że cała reszta wyświetlała polskie znaki poprawnie. Przerobiłem najpolularniejsze zalecenia, lecz bez skutku. Trafiłem tutaj i zaciekawił mnie fragment o spring-security, którego również w projekcie używam. Przeczytałem fragment o stosowaniu przez spring-security własnego kodowania bardzo literalnie i po krótkiej analizie web.xml, gdzie miałem taki porządek:
springSecurityFilterChain a poniżej encoding-filter najzwyczajniej w świecie zamieniłem je miejscami, tzn. encoding filter był przed springSecurityFilterChain w web.xml i ku mojemu zdziwieniu problem zniknął. Nie ukrywam, że trochę mnie to zdziwiło, jednak grunt, że działa.

1 użytkowników online, w tym zalogowanych: 0, gości: 1