如何让杰克逊在输出字符串中转义</脚本>

How to get Jackson to escape a </script> in output string?

本文关键字:脚本 转义 杰克逊 字符串 输出      更新时间:2023-09-26

我有一个简单的Java对象,我正在使用Jackson将其序列化为JSON,然后将其放入JSP页面中的<script>标记中,作为初始化JavaScript对象的一部分。 例如

<script>SomeLib.load(${someObject});</script>

由于此问题,除非某个对象的字段之一是包含"</script>"的字符串,否则这很好用。 也就是说,如果输出如下所示:

<script>SomeLib.load({"someValue":"hacked!</script>"});</script>

然后浏览器(到目前为止在 Chrome 和 FF 中都经过测试)认为 hacked! 之后的 </script> 标记正在关闭脚本标记。 这会破坏 JavaScript 并使"});</script>对用户可见。

有没有办法让杰克逊以某种方式摆脱这种价值来解决这个问题?

Ravis 的回答是错误的。在那里看到我的评论。

更好的方法是使用反斜杠转义</中的斜杠,例如:

<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
...
<script>SomeLib.load(${fn:replace(jsonString, "</", "<''/")});</script>

注意:需要两个反斜杠,以便在 JSP 语法中对第一个反斜杠进行转义。

好的部分是,它不需要特殊的解码。

PS:要在杰克逊方面做到这一点,请参阅此博客 - 它涵盖了转义其他字符,但只需在列表中添加斜杠即可转义(所有)斜杠字符。

您可以使用

JSTL 函数fn:replace()转义带有 &lt; 的起始<,这将有效地防止 JSON 字符串中的任何标签被解释为 HTML。

所以,这个

<script>SomeLib.load(${fn:replace(jsonString, "<", "&lt;")});</script>

将在浏览器中呈现正常,因为

<script>SomeLib.load({"someValue":"hacked!&lt;/script>"});</script>

但是,在使用replace()之前,您需要将 JSTL 函数标记库导入

<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>

不,这不起作用,因为

这就是重点,因为如果它以<的形式出现,它会破坏HTML解析器/浏览器。

您需要记住,当协议或应用程序对某些内容进行编码(例如浏览器以 UTF-8 编码的 URL 字符串)时,它也需要在使用之前进行解码(就像 Web 服务器在服务器端对 URL 所做的那样),否则功能可能会中断。

因此,既然您知道您的 JSON 字符串是半编码的,您还需要修改使用者;要么SomeLib.load()方法将&lt;替换为<,要么如果是第三方库,请在 Javascript 本身中解码其输入。

<script>
  var json = '${fn:replace(jsonString, "<", "&lt;")}';
  SomeLib.load(JSON.parse(json.replace("&lt;", "<")));
</script>