我在某些旧版代码中有一个错误,在尝试对其进行修复时,发现了我不理解的行为。该应用程序是使用JSP和JSTL的Spring MVC应用程序。下面是一个简化的示例,它复制了我正在谈论的行为。我控制器的代码是:
@GetMapping("/users/thing")
public ModelAndView thing() {
ModelAndView model = new ModelAndView("users/thing");
String stringWithApostrophe = "Any'String";
String escapedWithHtmlUtils = HtmlUtils.htmlEscape(stringWithApostrophe);
model.addObject("stringWithApostrophe", stringWithApostrophe);
model.addObject("escapedWithHtmlUtils", escapedWithHtmlUtils);
return model;
}
变量stringWithApostrophe
中包含撇号,然后我对其进行转义并将转义的值存储在其他变量中。之后,将它们都添加到模型中。
我的看法是这样的:
<p><a onClick="clicked('${stringWithApostrophe}');" href="#">stringWithApostrophe: ${stringWithApostrophe}</a></p>
<p><a onClick="clicked('${escapedWithHtmlUtils}');" href="#">escapedWithHtmlUtils: ${escapedWithHtmlUtils}</a></p>
<script type="text/javascript">
function clicked(text){
console.log(text);
}
</script>
如果我在浏览器中按CTRL+U
以查看页面的来源,则会看到以下内容:
<p><a onClick="clicked('Any'String');" href="#">stringWithApostrophe: Any'String</a></p>
<p><a onClick="clicked('Any'String');" href="#">escapedWithHtmlUtils: Any'String</a></p>
...看起来不错,并且呈现为:
...这也是我所期望的。当我单击第一个链接时,它也按预期失败,由于未转义的撇号破坏了JavaScript代码,浏览器控制台显示了错误消息Syntax error: missing ) after argument list
。
但是,尽管我希望第二个链接能够正常工作,但它也会失败,并显示相同的错误消息。为什么会这样呢?我无法理解,撇号已转换为CTRL+U
所示的html实体,因此它不应破坏javascript。我一直在互联网上寻找造成这种情况的可能原因,但没有发现任何问题。我想念什么?
更新:我上载了the example project,如果有帮助,我曾经将错误重现到Github。
答案 0 :(得分:1)
如您的问题所述,撇号已由HtmlUtils类成功转换为HTML实体引用,成为'
。之所以发生您描述的行为,是因为HTML解析器在将内容传递给JavaScript引擎之前会解析属性值中的实体引用。因此,onclick(...)
语句中的实体被解码为原始字符'
,如下所示。
onClick="clicked('Any'String');"
=> onClick="clicked('Any'String');"
。
因此,对于JS引擎,两个onClick(...)
语句是等效的。
有关此问题的更多信息,请参见this related discussion讨论。