提交表单中允许的字符(包括UTF-8)

提交表单中允许的字符(包括UTF-8),utf-8,ascii,Utf 8,Ascii,假设我允许我的用户提交一个包含一些文本字段的表单(我不是说密码)。我的用户偶尔会使用非ASCII字符,如俄语、汉语等,所以我在数据库中使用UTF-8字符集。问题是,我真的应该允许所有可能的UTF-8字符吗?我查看了ASCII表,发现字符0到31与文本无关,除了换行符和空格。字符176到223似乎是为了装饰目的:p。我应该限制它们吗?W3C在其示例正则表达式中跳过以下字符: 没有 尝试“预清理”用户输入是一个非常糟糕的主意。你认为“装饰”对另一种语言的读者来说是绝对必要的。最好的解决方案是将文本按

假设我允许我的用户提交一个包含一些文本字段的表单(我不是说密码)。我的用户偶尔会使用非ASCII字符,如俄语、汉语等,所以我在数据库中使用UTF-8字符集。问题是,我真的应该允许所有可能的UTF-8字符吗?我查看了ASCII表,发现字符0到31与文本无关,除了换行符和空格。字符176到223似乎是为了装饰目的:p。我应该限制它们吗?

W3C在其示例正则表达式中跳过以下字符:

没有


尝试“预清理”用户输入是一个非常糟糕的主意。你认为“装饰”对另一种语言的读者来说是绝对必要的。最好的解决方案是将文本按原样存储在数据库中,然后在写入页面之前对其进行清理。

确保它是有效的UTF-8和Unicode

确保它不包含某些字符,例如控制代码可能不需要

您应该知道,即使您在表单中使用UTF-8,当所有用户代理向您发送表单数据时,您可能无法从他们那里获得有效的UTF-8,并且您必须根据需要对其进行过滤。无效的UTF-8可以有多种形式,其中一些是

  • 过长的编码(可能导致安全问题)
  • 其他无效的UTF-8字节序列,这可能表明用户代理忽略了字符编码,并提交了类似Windows-1252或ISO-8859-1编码的内容
  • Unicode中位于保留代理项空间中的代码点
在输入过程中需要过滤掉以上所有内容,否则您将无法存储有效的Unicode

如果您希望提供使用Unicode子集的有效HTML或XHTML,则还需要过滤(在输入或输出时):

  • C0控制代码0x00至0x19(除制表符、空格、新行、回车外)
  • 0x7F
  • C1控制代码0x80至0xBF
  • (可能)0x10FFFF以上的任何代码点
    • 当你说“ASCII表”时,你说的是不是?那页是垃圾。只有前128个字符(即0..127)是“ASCII”;它们为数字128..255显示的映射来自一个名为的ASCII扩展名。有很多“扩展ASCII”,cp437远远不是最常见的

      但我离题了。你的问题不是关于字符编码,而是关于筛选,筛选应该基于字符的属性:是字母、数字还是控制字符?大多数现代编程语言提供了获取此类信息的方法或函数,并且大多数语言还提供了regex支持。至于你应该过滤什么,或者你是否应该过滤,只有你自己知道


      不过,听起来您需要更多地了解字符编码和Unicode

      我不同意。在所有处理(包括存储)之前,应对用户输入进行消毒。不这样做的好处是什么?如果您有过多或过少的净化输入,则无法恢复原始数据。如果存储了未受干扰的数据,则始终可以按照任何需要的方式对其进行清理。我同意,但另一方面,存储数据的例程可能会暴露一个漏洞,可使用恶意和未初始化的输入进行攻击。所有这些都是真的,Gumbo发布的正则表达式将处理所有这些问题。感谢您的回复。我想我将使用Gumbo建议的正则表达式来验证输入。它似乎可以处理您所说的要过滤掉的所有内容。是的,正则表达式适用于将在XHTML或HTML中使用的UTF-8编码文本,因为它还可以过滤掉上面提到的那些控制代码。PHP等价物应该是preg_match('/\A([\x09\x0A\x0D\x20-\x7E].[\xC2-\xDF][\x80-\xBF].\xE0-\xBF][\x80-\xBF].][\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}|\xED[\x80-\xBF][\x80-\xBF][\x90-\xBF][\x80-\xBF]{2}|[\xF1-\xF3][\x80-\xBF]{3}|\xF4[\x80-\xBF][\x80-\xBF]{2}\z/x',$string)“;我说的对吗?@bilygates:您也可以留下注释。PHP的
      preg_match
      使用与Perl兼容的正则表达式,
      x
      修饰符允许使用空格和注释(从
      开始直到行尾)使正则表达式更易于理解。是的,这正是我看到的页面。我不知道127-255字符可以不同。我会看看你推荐的那篇文章。谢谢!
      
      $field =~
        m/\A(
           [\x09\x0A\x0D\x20-\x7E]            # ASCII
         | [\xC2-\xDF][\x80-\xBF]             # non-overlong 2-byte
         |  \xE0[\xA0-\xBF][\x80-\xBF]        # excluding overlongs
         | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}  # straight 3-byte
         |  \xED[\x80-\x9F][\x80-\xBF]        # excluding surrogates
         |  \xF0[\x90-\xBF][\x80-\xBF]{2}     # planes 1-3
         | [\xF1-\xF3][\x80-\xBF]{3}          # planes 4-15
         |  \xF4[\x80-\x8F][\x80-\xBF]{2}     # plane 16
        )*\z/x;