2009-08-11 31 views
3

假設我允許我的用戶提交包含一些文本字段(我不是在談論密碼)的表單。我的用戶偶爾會使用非ASCII字符,如俄文,中文等,所以我在我的數據庫中使用UTF-8字符集。問題是,我是否應該真的允許所有可能的UTF-8字符?我看了一下ASCII表,看到字符0到31與文本無關,除了換行符和空格。人物176至223似乎是用於裝飾的目的:p。我應該限制他們嗎?提交表單中允許的字符(包括UTF-8)

回答

4

請確定它是有效的UTF-8和Unicode?

確保它不包含某些字符,如控制代碼? 可能沒有必要

你應該知道,即使您正在使用UTF-8表單,您可能無法從所有用戶代理得到有效的UTF-8時,他們將表單數據發送給你,你會必須根據需要進行過濾。無效的UTF-8可以採取多種形式,其中一些是

  • 超長編碼(這可能會導致安全問題)
  • 其他無效UTF-8字節序列,這可能表明該用戶代理忽略字符編碼,並提交了類似Windows-1252或ISO-8859-1編碼的內容。
  • 是位於預留空間替代以Unicode

以上所有需要的代碼點輸入時被過濾掉,否則你沒有存儲有效的Unicode。

如果你想爲有效的HTML或XHTML,它使用Unicode的一個子集,則還需要需要過濾掉(無論是在輸入或輸出):

  • C0控制碼0x00到0x19(除了標籤,空間,新的線,carraige返程)
  • 0x7F的
  • C1控制碼0x80至爲0xBF
  • (可能)的任何代碼點以上在0x10FFFF
+0

所有這些都是真實的,而Gumbo發佈的正則表達式將處理所有這些問題。 – 2009-08-12 07:29:50

+0

謝謝你的回覆。我想我會用Gumbo建議的用於驗證輸入的正則表達式。它似乎處理你說過濾的所有內容。 – liviucmg 2009-08-12 11:27:43

+0

是的,該正則表達式適用於將在XHTML或HTML中使用的UTF-8編碼文本,因爲它也會過濾掉上述那些控制代碼。 – thomasrutter 2009-08-16 14:42:32

6

的W3C跳過他們爲榜樣的正則表達式這些字符在Multilingual form encoding

這是一個非常糟糕的主意,嘗試「預清潔」用戶輸入

$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; 
+0

PHP的等效將是的preg_match('/ \ A( [\ X09 \ X0A \ X0D \ x20- \ x7E] | [\ xC2- \ XDF] [\ x80- \ XBF] | \ xE0 [\ xA0- \ xBF] [\ x80- \ xBF] | [\ xE1- \ xEC \ xEE \ xEF] [\ x80- \ xBF] {2} | \ xED [\ x80- \ x9F] [\ xBF] | \ xF0 [\ x90- \ xBF] [\ x80- \ xBF] {2} | [\ xF1- \ xF3] [\ x80- \ xBF] {3} | \ xF4 [ \ x80- \ x8F] [\ x80- \ xBF] {2} )* \ z/x',$ string); 我正確嗎? – liviucmg 2009-08-12 11:10:47

+1

@bilygates:你也可以留下評論。 PHP的'preg_match'使用Perl兼容的正則表達式,'x'修飾符允許使用空格和註釋(以'#'開始直到行尾)來使正則表達式更易於理解。 – Gumbo 2009-08-12 13:18:42

+0

@Gumbo好的,會的。非常感謝! – liviucmg 2009-08-13 10:44:28

1

號。你認爲「裝飾」可能是另一種語言的讀者絕對需要的。最好的解決方案是將文本原樣存儲在數據庫中,然後在寫入頁面之前對其進行清理。

+0

我不同意。用戶輸入應在所有處理(包括存儲)之前進行消毒。不這樣做的好處是什麼? – 2009-08-11 22:45:15

+0

如果您輸入的數據過多或數據不足,則無法恢復原始數據。如果存儲了未掃描的數據,則始終可以根據需要進行清理。 – 2009-08-11 22:52:15

+0

我同意,但另一方面,存儲數據的例程可能會暴露一個漏洞,可以利用惡意和未經處理的輸入來利用這個漏洞。 – 2009-08-11 23:16:01

1

當你說「ASCII碼錶」時,你說的是this page,不是嗎?該頁面是垃圾。只有前128個字符(即0..127)是「ASCII」;它們爲數字128..255顯示的映射來自名爲cp437的ASCII擴展。在那裏有很多「擴展的ASCII」,cp437遠不是最常見的。

但我離題了。你的問題不是關於字符編碼,而是關於過濾,過濾器應該基於字符的屬性:它是一個字母,一個數字,一個控制字符?大多數現代編程語言提供獲取這些信息的方法或功能,並且大多數也提供正則表達式支持。至於什麼你應該過濾,或者你是否應該過濾,只有你可以知道。

這聽起來像你需要了解更多關於字符編碼和Unicode的內容。 Start here.

+0

是的,那正是我看過的頁面。我不知道字符127 - 255可以不同。我會看看你推薦的那篇文章。謝謝! – liviucmg 2009-08-12 11:14:09