提到省略符,见多识广的国际化测试人员的第一反应应该会是法语。没错,在法语中的确充斥着这样的符号(俗称“撇号”)。一旦出现这样的符号,总是会涉及到转义问题,例如如下信息。在这里,细心的本地化人员已经为省略符做了转义。
message=Supprimer cette stratégie de tous les droits d''accèsliés ? Si vous cliquez sur OK, les demandes associées à cette stratégiene seront plus soumises à l''approbation, saufsi vous appliquez une autre stratégie.
然而在前端UI中转义符并未生效,撇号显示为不可读的字符串',如下图所示。
在深入分析该bug的成因前,首先需要介绍一下本例中涉及的技术背景XSS(Cross Site Scripting)——跨站脚本攻击。这是Web程序中最常见的漏洞之一。攻击者预先在网页中嵌入客户端脚本(例如JavaScript),当用户浏览此网页时,脚本程序就会在用户的浏览器上执行,从而达到攻击者的目的。例如可以获取用户的Cookie,导航到恶意网站,携带木马等。
这里我们可以清晰的看到,_title和_message这两个变量为了避免XSS攻击,都经过了htmlEscapeAllowEntities方法的转义处理。然而在初始化ImageLabel的时候,程序对lable的内容进行了二次转义,这就导致了HTML Entity在前端的出现。
现在我们了解了问题的成因,再次审视,不禁反思——这真的只是法文特有的国际化bug么?其他自然语言(例如英文)就不存在类似问题?
显然事实并非如此,英文中I'm, I didn't这样的词句依然可以触发该现象。那么当我们再次遇到这个所谓法文常见“国际化问题”时,还会不假思索的将其标识为国际化bug么?读到这里,相信大家已经有了自己的答案。
message=Supprimer cette stratégie de tous les droits d''accèsliés ? Si vous cliquez sur OK, les demandes associées à cette stratégiene seront plus soumises à l''approbation, saufsi vous appliquez une autre stratégie.
然而在前端UI中转义符并未生效,撇号显示为不可读的字符串',如下图所示。
在深入分析该bug的成因前,首先需要介绍一下本例中涉及的技术背景XSS(Cross Site Scripting)——跨站脚本攻击。这是Web程序中最常见的漏洞之一。攻击者预先在网页中嵌入客户端脚本(例如JavaScript),当用户浏览此网页时,脚本程序就会在用户的浏览器上执行,从而达到攻击者的目的。例如可以获取用户的Cookie,导航到恶意网站,携带木马等。
XSS攻击之所以会发生,归根结底是因为用户输入的数据变成了可执行代码。所以通常情况下,我们需要对用户输入的数据进行HTMLEncode处理,将其中的中括号、单引号、双引号之类的特殊字符进行编码。这就使得一个Web安全问题引入了国际化bug的潜在可能。
public PromptPanel(String title, String message, ImageResource imageResource, String okButtonText, String cancelButtonText) {
...
if (!StringUtil.isNullOrEmpty(title)) {
_title = SafeHtmlUtils.htmlEscapeAllowEntities(title);
}
if (!StringUtil.isNullOrEmpty(message)) {
_message = SafeHtmlUtils.htmlEscapeAllowEntities(message); // fixes XSS
}
...
}
这里我们可以清晰的看到,_title和_message这两个变量为了避免XSS攻击,都经过了htmlEscapeAllowEntities方法的转义处理。然而在初始化ImageLabel的时候,程序对lable的内容进行了二次转义,这就导致了HTML Entity在前端的出现。
private void initContent() {
<span style="white-space:pre"> </span>if (!StringUtil.isNullOrEmpty(_title)) {
<span style="white-space:pre"> </span>Label title = new Label(_title);
<span style="white-space:pre"> </span>container.add(title);
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>ImageLabel label = new ImageLabel(_message, _imageResource);
<span style="white-space:pre"> </span>…
}
public ImageLabel(String label, ImageSpec imageSpec) {
<span style="white-space:pre"> </span>this(new SafeHtmlBuilder().appendEscaped(label).toSafeHtml(), imageSpec);
}
现在我们了解了问题的成因,再次审视,不禁反思——这真的只是法文特有的国际化bug么?其他自然语言(例如英文)就不存在类似问题?
显然事实并非如此,英文中I'm, I didn't这样的词句依然可以触发该现象。那么当我们再次遇到这个所谓法文常见“国际化问题”时,还会不假思索的将其标识为国际化bug么?读到这里,相信大家已经有了自己的答案。