如何使用EL正确解码JSP中的cookie值?

时间:2015-09-02 16:50:21

标签: jsp curl el tomcat8

我想在JSP页面上显示cookie的值。使用EL,我精心制作了这个:

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

这似乎有效,但我不确定这是否会正确解码cookie值中的特殊URL字符。我使用curl做了一个快速测试:

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

因此它似乎无法正确解码%20字符序列。但是,这可能是curl的问题,而不是我的Tomcat实例。这是另一个需要:

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

我做错了什么?

1 个答案:

答案 0 :(得分:1)

${fn:escapeXml()}转义predefined XML entities。它与URL encoding nor decoding没有任何关联。另请参阅XSS prevention in JSP/Servlet web application

如果您使用的是EL 3.0(Tomcat 8支持它),那么您可以使用ELContext#getImportHandler()packagesclassesconstants导入EL范围。您可以使用它来导入包含所需java.net.URLDecoder方法的decode()类。

将它放在JSP的顶部:

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

然后您可以解码cookie,如下所示:

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

是的,导入该类的EL表达式以一种可怕的方式提醒遗留的 Scriptlets 。幸运的是,您可以在ServletContextListener的帮助下全局配置,如下所示:

@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");
            }
        });
    }

    // ...
}

另见: