1

I want to display the value of a cookie on a JSP page. Using EL, I crafted this:

<c:set var="errorFlash" value="${cookie['error']}"/>
<c:if test="${null != errorFlash}">
    <p>${fn:escapeXml(errorFlash.value)}</p>
</c:if>

This seems to work, but I am not sure if this would decode special URL characters in the cookie value correctly. I did a quick test using curl like this:

$ curl http://localhost:8080/login -v -b 'error=Hello%20World'
[...]
> Cookie: error=Hello%20World
[...]
<p>Hello%20World</p>
[...]

So it does not seem to decode the %20 character sequence correctly. However, this might be an issue with curl, not with my Tomcat instance. Here's another take:

$ curl http://localhost:8080/login -v -b 'error=Hello World'
[...]
> Cookie: error=Hello World
[...]
<p>Hello</p>
[...]

What am I doing wrong?

Christian Schlichtherle
  • 3,125
  • 1
  • 23
  • 47
  • Have a custom tag lib which decodes the data, or either (bad-way) a simple scriplet which decodes the value. –  Sep 02 '15 at 17:05

1 Answers1

1

The ${fn:escapeXml()} escapes predefined XML entities. It does not have any associations with URL encoding nor decoding. See also XSS prevention in JSP/Servlet web application.

Provided that you're on EL 3.0 (Tomcat 8 supports it), then you can use ELContext#getImportHandler() to import packages, classes and constants into EL scope. You can make use of it to import the java.net.URLDecoder class which contains the decode() method you need.

Put this somewhere in top of your JSP:

${pageContext.ELContext.importHandler.importClass('java.net.URLDecoder')}

Then you can decode the cookie as below:

<c:if test="${not empty cookie.error}">
    <p>${URLDecoder.decode(cookie.error.value, 'UTF-8')}</p>
</c:if>

True, that EL expression to import the class reminds in a scary way of legacy Scriptlets. Fortunately, you can configure this globally with help of a ServletContextListener like below:

@WebListener
public class Config implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent event) {
        JspFactory.getDefaultFactory().getJspApplicationContext(event.getServletContext()).addELContextListener(new ELContextListener() {
            @Override
            public void contextCreated(ELContextEvent event) {
                event.getELContext().getImportHandler().importClass("java.net.URLDecoder");
            }
        });
    }

    // ...
}

See also:

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555