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

How to properly decode cookie values in a JSP using EL?

我想在 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>
[...]

我做错了什么?

${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.

如果你使用的是EL 3.0(Tomcat8支持),那么你可以使用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()你需要的方法

把这个放在你的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>

是的,导入 class 的 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");
            }
        });
    }

    // ...
}

另请参阅: