国际字符的JavaScript验证问题

时间:2009-07-02 09:31:44

标签: javascript jquery validation internationalization

我们使用Stack Overflow上的优秀validator plugin for jQuery在输入提交到服务器之前对输入进行客户端验证。

它通常效果很好,然而,这个让我们摸不着头脑。

以下验证方法用于用户名字段的提问/答案表单(请注意,您必须已注销才能在实际网站上查看此字段;它位于每个{{1页面和/question页面)

/ask

现在这个正则表达式看起来很奇怪,但它非常简单:

  • 匹配字符串的开头(^)
  • 匹配其中任何一个..
    • 字符(\ w)
    • 破折号( - )
    • 空格(\ s)
    • 数字(\ d)
    • 疯狂的月亮语言字符(àèìòù等)
  • 现在匹配字符串的结尾($)

是的,我们遇到了Internationalized Regular Expressions问题。 JavaScript对“单词字符”的定义根本不包括国际字符。

这是一个奇怪的部分:尽管我们已经麻烦地手动将大量有效的国际字符添加到正则表达式,但它不起作用。如果没有获取..

,则无法在用户名的输入框中输入这些国际字符
  

只能包含A-Z,0-9,空格和连字符

..验证返回!

显然验证 正在为正则表达式的其他部分工作 ..所以...给出了什么?

另一个奇怪的部分是,此验证在浏览器的JavaScript控制台中有效,但在作为我们的标准* .js包含的一部分执行时则不行。

  

/ ^ [\ W- \sÀÈÌÒÙàèìòùÁÉÍÓÚÝáéíóúýÂÊÎÔÛâêîôûÃÑÕãñõÄËÏÖÜäëïöüçÇßØøÅåÆæÞþÐð] + $ /   .test('ÓBilldehÓra')=== true

我们之前在JavaScript代码中遇到过一些非常奇怪的国际角色问题,导致一些非常非常讨厌的黑客攻击。我们想了解这里发生了什么,为什么。请指教!

7 个答案:

答案 0 :(得分:36)

我认为电子邮件和网址验证方法在这里是一个很好的参考,例如。电子邮件方法:

email: function(value, element) {
    return this.optional(element) || /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i.test(value);
},

The script to compile that regex

换句话说,用这个替换你的“疯狂月亮”字符的任意列表可能会有所帮助:

[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]

基本上,这可以通过用更一般的定义替换needs-encoding字符来避免您在其他地方遇到的字符编码问题。虽然不一定更具可读性,但到目前为止它比您的完整列表更短。

答案 1 :(得分:13)

这不是一个真正的答案,但我还没有50个代表添加评论......它肯定会归因于编码问题。

是的“ECMA不应该关心编码......”等等等等,如果你使用的是Firefox,请转到查看>字符编码>西方(ISO-8859-1)然后尝试使用名称字段。

手动更改编码后,它对我来说很好(授予页面的其余部分不喜欢编码开关,:P)

(在IE8上,您可以转到页面>编码>西欧(Windows)以获得相同的效果)

答案 2 :(得分:3)

JS文件的字符编码是什么?

对于XML QNames,我使用此RegExp:

/**
 * Definition of an XML Name
 */
var NameStartChar = "A-Za-z:_\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D"+
                    "\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF"+
                    "\uF900-\uFDCF\uFDF0-\uFFFD\u010000-\u0EFFFF";
var NameChar = NameStartChar+"\\-\\.0-9\u00B7\u0300-\u036F\u203F-\u2040";
var Name = "^["+NameStartChar+"]["+NameChar+"]*$";
RegExp (Name).test (value);

它的魅力与国际化角色一样。注意逃避。因为我能够将JS文件限制为 ASCII 字符。因此,在处理ISO-8859与UTF-8字符集时,我不会遇到麻烦。

如果您使用ASCII不是真正子集的字符编码(例如,在亚洲UTF-16中),则情况不再如此。

干杯,

答案 3 :(得分:2)

列出的国际字符是扩展ASCII的一部分。你添加的那些肯定不是。

答案 4 :(得分:2)

看到该语句在控制台中有效,是否必须按照.js文件的保存方式(即ascii或UTF-8)进行操作,并且浏览器正在加载它们并在此过程中转换字符? / p>

答案 5 :(得分:2)

使用类似Fiddler或Charles(不是Firebug的Net面板,或其他任何实际位于浏览器中的内容)来检查实际传输的内容。这几乎可以肯定是一个编码问题:文件已保存在某些Microsoft字符集中,并以UTF-8格式发送,或者反过来。

对于JS RegExps,您可以像Boldewyn所指出的那样,通过为所需字符指定超出US-ASCII范围的Unicode代码点来避免这些问题。不过,确保你不会在保存文件的地方和服务地点之间混合编码也是一样。

答案 6 :(得分:2)

这里游戏的后期,但我只是使用了这个表达式,它似乎对我有用。似乎相当全面且相对简单:

var re = /^[A-zÀ-ÿ\s\d-]*$/g; 
var str1 = 'casa-me,pois 99 estou farto! Eis a lista:uma;duas;três';
var str2 = 'casa-me pois 99 estou farto Eis a lista uma duas três';

alert(re.test(str1));
alert(re.test(str2));