Error with cookie-value when adding a new Spring Session
Asked Answered
A

5

17

In my Spring Boot 1.4 based application I use Spring Session to store session data in the database with JDBC.

This works fine with the default session. But when I want to add a new session (by adding ?_s=1 to the application url) I get the following exception:

java.lang.IllegalArgumentException: An invalid character [32] was present in the Cookie value

What is the issue here?

Edit: Note that I do not set the cookie value myself, Spring Session does that. Thus I can not tell which value it tries to set.

The complete stacktrace is here:

java.lang.IllegalArgumentException: An invalid character [32] was present in the Cookie value
    at org.apache.tomcat.util.http.Rfc6265CookieProcessor.validateCookieValue(Rfc6265CookieProcessor.java:160) ~[tomcat-embed-core-8.5.4.jar:8.5.4]
    at org.apache.tomcat.util.http.Rfc6265CookieProcessor.generateHeader(Rfc6265CookieProcessor.java:109) ~[tomcat-embed-core-8.5.4.jar:8.5.4]
    at org.apache.catalina.connector.Response.generateCookieString(Response.java:989) ~[tomcat-embed-core-8.5.4.jar:8.5.4]
    at org.apache.catalina.connector.Response.addCookie(Response.java:937) ~[tomcat-embed-core-8.5.4.jar:8.5.4]
    at org.apache.catalina.connector.ResponseFacade.addCookie(ResponseFacade.java:386) ~[tomcat-embed-core-8.5.4.jar:8.5.4]
    at org.springframework.session.web.http.DefaultCookieSerializer.writeCookieValue(DefaultCookieSerializer.java:112) ~[spring-session-1.2.1.RELEASE.jar:na]
    at org.springframework.session.web.http.CookieHttpSessionStrategy.onNewSession(CookieHttpSessionStrategy.java:213) ~[spring-session-1.2.1.RELEASE.jar:na]
    at org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper.commitSession(SessionRepositoryFilter.java:247) ~[spring-session-1.2.1.RELEASE.jar:na]
    at org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper.access$100(SessionRepositoryFilter.java:214) ~[spring-session-1.2.1.RELEASE.jar:na]
    at org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryResponseWrapper.onResponseCommitted(SessionRepositoryFilter.java:202) ~[spring-session-1.2.1.RELEASE.jar:na]
    at org.springframework.session.web.http.OnCommittedResponseWrapper.doOnResponseCommitted(OnCommittedResponseWrapper.java:226) ~[spring-session-1.2.1.RELEASE.jar:na]
    at org.springframework.session.web.http.OnCommittedResponseWrapper.sendRedirect(OnCommittedResponseWrapper.java:126) ~[spring-session-1.2.1.RELEASE.jar:na]
    at javax.servlet.http.HttpServletResponseWrapper.sendRedirect(HttpServletResponseWrapper.java:138) ~[tomcat-embed-core-8.5.4.jar:8.5.4]
    at javax.servlet.http.HttpServletResponseWrapper.sendRedirect(HttpServletResponseWrapper.java:138) ~[tomcat-embed-core-8.5.4.jar:8.5.4]
    at org.springframework.security.web.firewall.FirewalledResponse.sendRedirect(FirewalledResponse.java:41) ~[spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
    at javax.servlet.http.HttpServletResponseWrapper.sendRedirect(HttpServletResponseWrapper.java:138) ~[tomcat-embed-core-8.5.4.jar:8.5.4]
    at org.springframework.security.web.util.OnCommittedResponseWrapper.sendRedirect(OnCommittedResponseWrapper.java:128) ~[spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
    at javax.servlet.http.HttpServletResponseWrapper.sendRedirect(HttpServletResponseWrapper.java:138) ~[tomcat-embed-core-8.5.4.jar:8.5.4]
    at org.springframework.security.web.util.OnCommittedResponseWrapper.sendRedirect(OnCommittedResponseWrapper.java:128) ~[spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
    at org.springframework.security.web.DefaultRedirectStrategy.sendRedirect(DefaultRedirectStrategy.java:57) ~[spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
    at org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint.commence(LoginUrlAuthenticationEntryPoint.java:169) ~[spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
    at org.springframework.security.web.access.ExceptionTranslationFilter.sendStartAuthentication(ExceptionTranslationFilter.java:204) ~[spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
    at org.springframework.security.web.access.ExceptionTranslationFilter.handleSpringSecurityException(ExceptionTranslationFilter.java:178) ~[spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:134) ~[spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) ~[spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137) ~[spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) ~[spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111) ~[spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) ~[spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
    at org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter.doFilter(RememberMeAuthenticationFilter.java:150) ~[spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) ~[spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:169) ~[spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) ~[spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63) ~[spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) ~[spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:200) ~[spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) ~[spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:121) ~[spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) ~[spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:66) ~[spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) ~[spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105) ~[spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) ~[spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56) ~[spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) ~[spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214) ~[spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177) ~[spring-security-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346) ~[spring-web-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262) ~[spring-web-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) ~[tomcat-embed-core-8.5.4.jar:8.5.4]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) ~[tomcat-embed-core-8.5.4.jar:8.5.4]
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) ~[spring-web-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) ~[tomcat-embed-core-8.5.4.jar:8.5.4]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) ~[tomcat-embed-core-8.5.4.jar:8.5.4]
    at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:87) ~[spring-web-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) ~[tomcat-embed-core-8.5.4.jar:8.5.4]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) ~[tomcat-embed-core-8.5.4.jar:8.5.4]
    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77) ~[spring-web-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) ~[tomcat-embed-core-8.5.4.jar:8.5.4]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) ~[tomcat-embed-core-8.5.4.jar:8.5.4]
    at org.springframework.session.web.http.SessionRepositoryFilter.doFilterInternal(SessionRepositoryFilter.java:164) ~[spring-session-1.2.1.RELEASE.jar:na]
    at org.springframework.session.web.http.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:80) ~[spring-session-1.2.1.RELEASE.jar:na]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) ~[tomcat-embed-core-8.5.4.jar:8.5.4]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) ~[tomcat-embed-core-8.5.4.jar:8.5.4]
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) ~[spring-web-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) ~[tomcat-embed-core-8.5.4.jar:8.5.4]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) ~[tomcat-embed-core-8.5.4.jar:8.5.4]
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198) ~[tomcat-embed-core-8.5.4.jar:8.5.4]
    at org.apache.catalina.core.StandardContextValve.__invoke(StandardContextValve.java:108) [tomcat-embed-core-8.5.4.jar:8.5.4]
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java) [tomcat-embed-core-8.5.4.jar:8.5.4]
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:522) [tomcat-embed-core-8.5.4.jar:8.5.4]
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) [tomcat-embed-core-8.5.4.jar:8.5.4]
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) [tomcat-embed-core-8.5.4.jar:8.5.4]
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) [tomcat-embed-core-8.5.4.jar:8.5.4]
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:349) [tomcat-embed-core-8.5.4.jar:8.5.4]
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:1110) [tomcat-embed-core-8.5.4.jar:8.5.4]
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.4.jar:8.5.4]
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:785) [tomcat-embed-core-8.5.4.jar:8.5.4]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1425) [tomcat-embed-core-8.5.4.jar:8.5.4]
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.4.jar:8.5.4]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_101]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_101]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.4.jar:8.5.4]
    at java.lang.Thread.run(Thread.java:745) [na:1.8.0_101]
Astound answered 31/7, 2016 at 18:35 Comment(4)
What is the value you are trying to set on the cookie?Pipe
Possible duplicate of java.lang.IllegalArgumentException: Control character in cookie value or attributeRigby
I don't know which value Spring Session wants to set in the cookie.Astound
You can inspect the value of cookie Spring Session attempts to write by placing a breakpoint at DefaultCookieSerializer.java:112 (which is the 6th line from your stackrace).Douse
D
20

This is due to Tomcat's cookie processing being changed to a RFC 6265 compliant implementation by default in 8.5, which does not allow space (character 32), among others.

As a workaround, you can configure Tomcat to use legacy cookie processor. To do this with Spring Boot, register an EmbeddedServletContainerCustomizer @Bean like this:

@Bean
public EmbeddedServletContainerCustomizer customizer() {
    return container -> {
        if (container instanceof TomcatEmbeddedServletContainerFactory) {
            TomcatEmbeddedServletContainerFactory tomcat = (TomcatEmbeddedServletContainerFactory) container;
            tomcat.addContextCustomizers(context -> context.setCookieProcessor(new LegacyCookieProcessor()));
        }
    };
}

Also see spring-projects/spring-session#gh-605 to track the progress of fixing this in Spring Session.

Update:

The above described solution is valid for Spring Boot 1.x. Starting with Spring Boot 2.0, EmbeddedServletContainerCustomizer has been replaced with WebServerFactoryCustomizer as described in the Spring Boot 2.0 migration guide.

Also note that starting with Spring Session 2.0, session cookie is Base64 encoded by default which prevents the original problem from occurring.

Douse answered 28/8, 2016 at 22:16 Comment(5)
how to handle '=' in Cookie (Base 64 encoded) ? Legacy fails for cookie parsing.Regulator
Hi there, what are the options for Spring 2.* ? There are no EmbeddedServletContainerCustomizer on its dependencies. Thanks.Randell
@JorgeCampos The EmbeddedServletContainerCustomizer has been renamed to WebServerFactoryCustomizer in Spring Boot 2.0. Please refer to Spring Boot 2.0 migration guide.Douse
Thank Vedran. Appreciated. Cheers,Randell
Spring Boot 2 version - gist.github.com/fedotxxl/10ff957c40bd166717d6c177ed14f92dGog
S
15

Function cookie cannot encode properly the value with space also french signs and so on. I solve this problem with URLEncoder.encode(String arg0, Encoding version) here I used UTF-8. Here the method I created!

private static void setCookie( HttpServletResponse response, String nom, String valeur, int maxAge )throws IOException { 
    Cookie cookie = new Cookie( nom, URLEncoder.encode( valeur, "UTF-8" ) );
    cookie.setMaxAge( maxAge );
    response.addCookie( cookie );
}
Salcido answered 21/9, 2017 at 18:20 Comment(2)
it's better that we should add a single line of code in the context file as suggested by https://mcmap.net/q/688334/-error-with-cookie-value-when-adding-a-new-spring-sessionJunkman
@SyedZeeshanAli No, we shouldn't use outdated code. Nobody should ever use *Legacy*CookieProcessor ever, if that could be avoided. Nobody should write new code that is already deprecated right from the start!Anemochore
E
14

CookieProcessor is a new configuration element, introduced in Tomcat 8.0.15. The CookieProcessor element allows different cookie parsing configuration in each web application, or globally in the default conf/context.xml file.

According to official docs at Apache Tomcat 8 Configuration Reference Version 8.0.47 :

The standard implementation of CookieProcessor is: org.apache.tomcat.util.http.LegacyCookieProcessor. Note that it is anticipated that this will change to org.apache.tomcat.util.http.Rfc6265CookieProcessor in a future Tomcat 8 release.

Later..

According to official docs at Apache Tomcat 8 Configuration Reference Version 8.5.23:

The standard implementation of CookieProcessor is org.apache.tomcat.util.http.Rfc6265CookieProcessor.

To resolve this issue: add this line in conf/context.xml at location %CATALINA_HOME% (i.e. C:\apache-tomcat-8.5.20\conf\context.xml in my case):

<CookieProcessor className="org.apache.tomcat.util.http.LegacyCookieProcessor" />

This is how it looks like after adding:

<?xml version="1.0" encoding="UTF-8"?>

<Context reloadable="true">
    <WatchedResource>WEB-INF/web.xml</WatchedResource>
    <WatchedResource>${catalina.base}/conf/web.xml</WatchedResource>
    <Transaction factory="bitronix.tm.BitronixUserTransactionObjectFactory"/>
    <CookieProcessor className="org.apache.tomcat.util.http.LegacyCookieProcessor" />    
</Context>
Exclamatory answered 12/10, 2017 at 5:53 Comment(0)
C
2

we can apply cookieValue.trim() or cookieValue.replace(" ", "") to remove whitespaces or "spcbefore

Consignor answered 15/3, 2020 at 5:56 Comment(0)
O
-1

Don't use whitespaces in the content of the cookie. It is mentioning whitespace as the invalid character.

Orestes answered 27/12, 2017 at 13:3 Comment(2)
Answer in proper way so that others can understand.Jujube
I'm new in Stack Overflow, so I know the answer I posted but how to add the code that I don't know.Orestes

© 2022 - 2025 — McMap. All rights reserved.