我有一个简单的Java对象,我正在使用Jackson序列化为JSON,然后我将其放入JSP页面中的<script>
标记中,作为初始化JavaScript对象的一部分。 e.g。
<script>SomeLib.load(${someObject});</script>
这非常有用,除非 someObject的某个字段是包含"</script>"
的字符串,因为this issue。也就是说,如果输出如下所示:
<script>SomeLib.load({"someValue":"hacked!</script>"});</script>
然后浏览器(目前在Chrome和FF中均经过测试)认为</script>
后hacked!
代码正在关闭脚本代码。这打破了JavaScript并使"});</script>
对用户可见。
有没有办法让杰克逊以某种方式逃避这个价值来解决这个问题呢?
答案 0 :(得分:3)
Ravis answer错了。在那里看我的评论。
更好的方法是使用反斜杠转义</
中的斜杠,例如:
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
...
<script>SomeLib.load(${fn:replace(jsonString, "</", "<\\/")});</script>
注意:需要两个反斜杠,以便在JSP语法中转义第一个反斜杠。
好的部分是,它不需要特殊的解码。
PS:要在杰克逊方面做,请参阅this blog - 它包括转义其他字符,但只需在列表中添加斜杠以转义(全部)斜杠字符。
答案 1 :(得分:0)
您可以使用JSTL函数fn:replace()
仅使用<
转义<
,这将有效防止JSON 字符串中的任何标记被解释作为HTML。
所以,这个
<script>SomeLib.load(${fn:replace(jsonString, "<", "<")});</script>
将在浏览器中呈现为
<script>SomeLib.load({"someValue":"hacked!</script>"});</script>
但是,在使用replace()
之前,您需要将JSTL 函数标记库导入为
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
不,这不会起作用,因为&lt;字面意思是在JavaScript字符串中(它没有转义)。
这就是重点,因为如果它以<
形式出现,它将破坏HTML解析器/浏览器。
您需要记住,当协议或应用程序对某些内容进行编码时(如浏览器以UTF-8编码的URL字符串),在使用之前也需要对其进行解码(就像Web服务器使用URL时所做的那样)服务器端)或功能可能会中断。
因此,既然您知道您的JSON字符串是半编码的,那么您还需要修改消费者;将SomeLib.load()
替换为<
的{{1}}方法,或者如果是第三方库,则在Javascript中解码其输入。
<