Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Property to control URL decoding in ServletCookieValueMethodArgumentResolver #26989

Closed
jakub-bochenski opened this issue May 27, 2021 · 11 comments
Assignees
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) type: enhancement A general enhancement
Milestone

Comments

@jakub-bochenski
Copy link

If I send a request with

Cookie: Nonce=Tl=Q/0AUSOx[n)2z4(t]20FZv#?[Ge%H

Spring will fail with

java.lang.IllegalArgumentException: Invalid encoded sequence "%H"
	at org.springframework.util.StringUtils.uriDecode(StringUtils.java:780)
	at org.springframework.web.util.UriUtils.decode(UriUtils.java:372)
	at org.springframework.web.util.UrlPathHelper.decodeInternal(UrlPathHelper.java:522)
	at org.springframework.web.util.UrlPathHelper.decodeRequestString(UrlPathHelper.java:513)
	at org.springframework.web.servlet.mvc.method.annotation.ServletCookieValueMethodArgumentResolver.resolveName(ServletCookieValueMethodArgumentResolver.java:66)
	at org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver.resolveArgument(AbstractNamedValueMethodArgumentResolver.java:108)
	at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:121)
	at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:167)
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:134)
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:878)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:792)
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
	at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:652)
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)

Affects: 5.2.14

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label May 27, 2021
@jakub-bochenski
Copy link
Author

SO: https://stackoverflow.com/q/67725851/1237617

How can I disable this?

@rstoyanchev
Copy link
Contributor

Thanks for getting in touch, but it feels like this is a question that would be better suited to Stack Overflow. As mentioned in the guidelines for contributing, we prefer to use the issue tracker only for bugs and enhancements.

@snicoll snicoll changed the title [spring-web] Spring URL-decodes my cookie and breaks Spring URL-decodes my cookie and breaks Jun 1, 2021
@snicoll snicoll added for: stackoverflow A question that's better suited to stackoverflow.com and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Jun 1, 2021
@jakub-bochenski
Copy link
Author

This is a bug, Spring should not throw IllegalArgumentException on valid input
I want to consume cookies with % character and it's not possible with Spring now

@jakub-bochenski
Copy link
Author

I see this breaking change was introduced last year: #11945

So how about a request for enahancement: add a parameter to @cookie annotation to support previous behaviour

@rstoyanchev
Copy link
Contributor

That issue is about 11 years old and the behavior has been in place for as long. Trying to find an RFC to justify the behavior of decoding the value, I see this in https://datatracker.ietf.org/doc/html/rfc6265#section-5.4:

Despite its name, the cookie-string is actually a sequence of
octets, not a sequence of characters. To convert the cookie-string
(or components thereof) into a sequence of characters (e.g., for
presentation to the user), the user agent might wish to try using the
UTF-8 character encoding [RFC3629] to decode the octet sequence.
This decoding might fail, however, because not every sequence of
octets is valid UTF-8.

So the behavior is seems OK, and it's been in use for so long, but you can also bypass @CookieValue and have ServletRequest injected instead to access the cooking value directly from it.

@jakub-bochenski
Copy link
Author

I fail to see the relevance of decoding octet sequences into UTF-8 character string for URL decoding the value later.

That issue is about 11 years old and the behavior has been in place for as long.

I'm sorry for taking the comment dates at face value :(

spring-projects-issues commented on Jun 20, 2010

@rstoyanchev
Copy link
Contributor

rstoyanchev commented Jun 1, 2021

You're right. Not the same as percent-encoded octets. At the moment I'm not seeing justification for the current behavior but it has been in place for very long, we could only correct it in a major or minor version. Also, that long ago, it's possible that there were other factors, like cookie values actually being encoded, as in that report which requested it.

In the mean time, if this causes an issue, the best I can think of is either access the cookie value directly from the request, or create your own annotation and register a resolver for it.

@rstoyanchev rstoyanchev reopened this Jun 1, 2021
@rstoyanchev rstoyanchev added in: web Issues in web modules (web, webmvc, webflux, websocket) type: enhancement A general enhancement and removed for: stackoverflow A question that's better suited to stackoverflow.com labels Jun 1, 2021
@rstoyanchev rstoyanchev added this to the 6.0 M1 milestone Jun 1, 2021
@jakub-bochenski
Copy link
Author

I think one easy improvement would be updating the Javadoc for @cookie annotation, since now it makes no mention of the URL decoding. It might be documented somewhere in Spring Reference docs but obviously Javadoc is more visible

In the mean time, if this causes an issue, the best I can think of is either access the cookie value directly from the request, or create your own annotation and register a resolver for it.

Wouldn't I be able to override the default handler for the @cookie annotation? I think this wold be the best for now. (I don't like using ServletRequest object, I might as well go back to using servlets then :))

I think a parameter to toggle the decoding would also be useful and you could set the default value to match the existing behaviour

rstoyanchev added a commit that referenced this issue Jun 2, 2021
@rstoyanchev
Copy link
Contributor

rstoyanchev commented Jun 2, 2021

I've updated the Javadoc for @CookieValue and realized you can also declare the argument to be javax.servlet.http.Cookie as an alternative to injecting the request.

For argument resolvers it's easy to add custom ones, but replacing the built-in ones is not straight forward.

For the annotation attribute, if the behavior isn't backed by the spec and if there isn't a reason to URL decode the value, then it doesn't make sense to have it, only to then have it removed in 6.0.

Zoran0104 pushed a commit to Zoran0104/spring-framework that referenced this issue Aug 20, 2021
@jhoeller jhoeller modified the milestones: 6.0 M1, 6.0.x Nov 16, 2021
lxbzmy pushed a commit to lxbzmy/spring-framework that referenced this issue Mar 26, 2022
@rstoyanchev
Copy link
Contributor

Given the long standing behavior, I would go with a plan to make this configurable, through a property on ServletCookieValueMethodArgumentResolver. Along with that, we'll probably need an extendArgumentResolvers(List<HandlerMethodArgumentResolver>) method on WebMvcConfigurer in order to allow setting a property on a built-in resolver.

@rstoyanchev rstoyanchev changed the title Spring URL-decodes my cookie and breaks Property to control URL decoding in ServletCookieValueMethodArgumentResolver Mar 7, 2023
@rstoyanchev rstoyanchev modified the milestones: 6.0.x, 6.1.x Mar 7, 2023
@rstoyanchev rstoyanchev self-assigned this Dec 5, 2023
@rstoyanchev rstoyanchev removed this from the 6.1.x milestone Dec 5, 2023
@rstoyanchev rstoyanchev added this to the 6.1.2 milestone Dec 5, 2023
@henrywangsk
Copy link

Hi @rstoyanchev, good job and noticed the ServletCookieValueMethodArgumentResolver has been implemented. How can it be configured (so we can set the urlDecode property to false)? Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

6 participants