開(kāi)發(fā)Web的一個(gè)原則就是表單驗(yàn)證不能為空,不能信任用戶(hù)輸入的任何信息,所以驗(yàn)證和過(guò)濾用戶(hù)的輸入信息就變得非常重要,我們經(jīng)常會(huì)在微博、新聞中聽(tīng)到某某網(wǎng)站被入侵了,存在什么漏洞,這些大多是因?yàn)榫W(wǎng)站對(duì)于用戶(hù)輸入的信息沒(méi)有做嚴(yán)格的驗(yàn)證引起的,所以為了編寫(xiě)出安全可靠的Web程序,驗(yàn)證表單輸入的意義重大。
我們平常編寫(xiě)Web應(yīng)用主要有兩方面的數(shù)據(jù)驗(yàn)證,一個(gè)是在頁(yè)面端的js驗(yàn)證(目前在這方面有很多的插件庫(kù),比如插件),一個(gè)是在服務(wù)器端的驗(yàn)證,我們這小節(jié)講解的是如何在服務(wù)器端驗(yàn)證。
必填字段
你想要確保從一個(gè)表單元素中得到一個(gè)值,例如前面小節(jié)里面的用戶(hù)名,我們?nèi)绾翁幚砟兀縂o有一個(gè)內(nèi)置函數(shù)len可以獲取字符串的長(zhǎng)度,這樣我們就可以通過(guò)len來(lái)獲取數(shù)據(jù)的長(zhǎng)度,例如:
if len(r.Form["username"][0])==0{
//為空的處理
}
r.Form對(duì)不同類(lèi)型的表單元素的留空有不同的處理, 對(duì)于空文本框、空文本區(qū)域以及文件上傳,元素的值為空值,而如果是未選中的復(fù)選框和單選按鈕,則根本不會(huì)在r.Form中產(chǎn)生相應(yīng)條目,如果我們用上面例子中的方式去獲取數(shù)據(jù)時(shí)程序就會(huì)報(bào)錯(cuò)。所以我們需要通過(guò)r.Form.Get()來(lái)獲取值,因?yàn)槿绻侄尾淮嬖冢ㄟ^(guò)該方式獲取的是空值。但是通過(guò)r.Form.Get()只能獲取單個(gè)的值,如果是map的值,必須通過(guò)上面的方式來(lái)獲取。
數(shù)字
你想要確保一個(gè)表單輸入框中獲取的只能是數(shù)字,例如,你想通過(guò)表單獲取某個(gè)人的具體年齡是50歲還是10歲,而不是像"一把年紀(jì)了"或"年輕著呢"這種描述
如果我們是判斷正整數(shù),那么我們先轉(zhuǎn)化成int類(lèi)型,然后進(jìn)行處理
getint,err:=strconv.Atoi(r.Form.Get("age"))
if err!=nil{
//數(shù)字轉(zhuǎn)化出錯(cuò)了,那么可能就不是數(shù)字
}
//接下來(lái)就可以判斷這個(gè)數(shù)字的大小范圍了
if getint >100 {
//太大了
}
還有一種方式就是正則匹配的方式
if m, _ := regexp.MatchString("^[0-9]+$", r.Form.Get("age")); !m {
return false
}
對(duì)于性能要求很高的用戶(hù)來(lái)說(shuō),這是一個(gè)老生常談的問(wèn)題了,他們認(rèn)為應(yīng)該盡量避免使用正則表達(dá)式,因?yàn)槭褂谜齽t表達(dá)式的速度會(huì)比較慢。但是在目前機(jī)器性能那么強(qiáng)勁的情況下,對(duì)于這種簡(jiǎn)單的正則表達(dá)式效率和類(lèi)型轉(zhuǎn)換函數(shù)是沒(méi)有什么差別的。如果你對(duì)正則表達(dá)式很熟悉,而且你在其它語(yǔ)言中也在使用它,那么在Go里面使用正則表達(dá)式將是一個(gè)便利的方式。
Go實(shí)現(xiàn)的正則是RE2,所有的字符都是UTF-8編碼的。
中文
有時(shí)候我們想通過(guò)表單元素獲取一個(gè)用戶(hù)的中文名字,但是又為了保證獲取的是正確的中文,我們需要進(jìn)行驗(yàn)證,而不是用戶(hù)隨便的一些輸入。對(duì)于中文我們目前有兩種方式來(lái)驗(yàn)證,可以使用包提供的func Is( *, r rune) bool來(lái)驗(yàn)證,也可以使用正則方式來(lái)驗(yàn)證,這里使用最簡(jiǎn)單的正則方式,如下代碼所示
if m, _ := regexp.MatchString("^\\p{Han}+$", r.Form.Get("realname")); !m {
return false
}
英文
我們期望通過(guò)表單元素獲取一個(gè)英文值,例如我們想知道一個(gè)用戶(hù)的英文名,應(yīng)該是,而不是asta謝。
我們可以很簡(jiǎn)單的通過(guò)正則驗(yàn)證數(shù)據(jù):
if m, _ := regexp.MatchString("^[a-zA-Z]+$", r.Form.Get("engname")); !m {
return false
}
電子郵件地址
你想知道用戶(hù)輸入的一個(gè)Email地址是否正確,通過(guò)如下這個(gè)方式可以驗(yàn)證:
if m, _ := regexp.MatchString(`^([\w\.\_]{2,10})@(\w{1,}).([a-z]{2,4})$`, r.Form.Get("email")); !m {
fmt.Println("no")
fmt.Println("yes")
}
手機(jī)號(hào)碼
你想要判斷用戶(hù)輸入的手機(jī)號(hào)碼是否正確,通過(guò)正則也可以驗(yàn)證:
if m, _ := regexp.MatchString(`^(1[3|4|5|8][0-9]\d{4,8})$`, r.Form.Get("mobile")); !m {
return false
}
下拉菜單
如果我們想要判斷表單里面元素生成的下拉菜單中是否有被選中的項(xiàng)目。有些時(shí)候黑客可能會(huì)偽造這個(gè)下拉菜單不存在的值發(fā)送給你,那么如何判斷這個(gè)值是否是我們預(yù)設(shè)的值呢?
我們的可能是這樣的一些元素

那么我們可以這樣來(lái)驗(yàn)證
slice:=[]string{"apple","pear","banana"}
v := r.Form.Get("fruit")
for _, item := range slice {
if item == v {
return true
}
}
return false
單選按鈕
如果我們想要判斷radio按鈕是否有一個(gè)被選中了,我們頁(yè)面的輸出可能就是一個(gè)男、女性別的選擇,但是也可能一個(gè)15歲大的無(wú)聊小孩,一手拿著http協(xié)議的書(shū),另一只手通過(guò)客戶(hù)端向你的程序在發(fā)送請(qǐng)求呢表單驗(yàn)證不能為空,你設(shè)定的性別男值是1,女是2,他給你發(fā)送一個(gè)3,你的程序會(huì)出現(xiàn)異常嗎?因此我們也需要像下拉菜單的判斷方式類(lèi)似,判斷我們獲取的值是我們預(yù)設(shè)的值,而不是額外的值。
男
女
那我們也可以類(lèi)似下拉菜單的做法一樣
slice:=[]string{"1","2"}

for _, v := range slice {
if v == r.Form.Get("gender") {
return true
}
}
return false
復(fù)選框
有一項(xiàng)選擇興趣的復(fù)選框,你想確定用戶(hù)選中的和你提供給用戶(hù)選擇的是同一個(gè)類(lèi)型的數(shù)據(jù)。
足球
籃球
網(wǎng)球
對(duì)于復(fù)選框我們的驗(yàn)證和單選有點(diǎn)不一樣,因?yàn)榻邮盏降臄?shù)據(jù)是一個(gè)slice
slice:=[]string{"football","basketball","tennis"}
a:=Slice_diff(r.Form["interest"],slice)
if a == nil{
return true
}
return false
上面這個(gè)函數(shù)包含在我開(kāi)源的一個(gè)庫(kù)里面(操作slice和map的庫(kù)),
日期和時(shí)間
你想確定用戶(hù)填寫(xiě)的日期或時(shí)間是否有效。例如 ,用戶(hù)在日程表中安排8月份的第45天開(kāi)會(huì),或者提供未來(lái)的某個(gè)時(shí)間作為生日。
Go里面提供了一個(gè)time的處理包,我們可以把用戶(hù)的輸入年月日轉(zhuǎn)化成相應(yīng)的時(shí)間,然后進(jìn)行邏輯判斷
t := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
fmt.Printf("Go launched at %s\n", t.Local())
獲取time之后我們就可以進(jìn)行很多時(shí)間函數(shù)的操作。具體的判斷就根據(jù)自己的需求調(diào)整。
身份證號(hào)碼
如果我們想驗(yàn)證表單輸入的是否是身份證,通過(guò)正則也可以方便的驗(yàn)證,但是身份證有15位和18位,我們兩個(gè)都需要驗(yàn)證
//驗(yàn)證15位身份證,15位的是全部數(shù)字
if m, _ := regexp.MatchString(`^(\d{15})$`, r.Form.Get("usercard")); !m {
return false
}
//驗(yàn)證18位身份證,18位前17位為數(shù)字,最后一位是校驗(yàn)位,可能為數(shù)字或字符X。
if m, _ := regexp.MatchString(`^(\d{17})([0-9]|X)$`, r.Form.Get("usercard")); !m {
return false
}
上面列出了我們一些常用的服務(wù)器端的表單元素驗(yàn)證,希望通過(guò)這個(gè)引導(dǎo)入門(mén),能夠讓你對(duì)Go的數(shù)據(jù)驗(yàn)證有所了解,特別是Go里面的正則處理。
links
文章列表
友情鏈接: 餐飲加盟
地址:北京市海淀區(qū) 電話(huà):010- 郵箱:@126.com
備案號(hào):冀ICP備2024067069號(hào)-3 北京科技有限公司版權(quán)所有