完成了第二小节过滤数据

This commit is contained in:
astaxie
2012-10-15 18:10:13 +08:00
parent 95c2368bde
commit 9530522908

46
9.2.md
View File

@@ -15,8 +15,54 @@
##过滤数据
在知道数据来源之后,就可以过滤它了。过滤是一个有点正式的术语,它在平时表述中有很多同义词,如验证、清洁及净化。尽管这些大家平时所用的术语稍有不同,但它们都是指的同一个处理:防止非法数据进入你的应用。
过滤数据有很多种方法其中有一些安全性较但最好的方法是把过滤看成是一个检查的过程在你使用数据之前都检查一下是否符合你的设计。请不要试图好心地去纠正非法数据要让你的用户按你的规则去做历史证明了试图纠正非法数据往往会导致安全漏洞。这里举个例子最近建设银行系统升级之后密码后面两位是0的只要输入前面四位就能登录系统一样这是一个非常严重的漏洞这个漏洞应该就是纠正非法数据引起的这种安全漏洞是非常严重的。
一般过滤数据主要采用如下一些库来操作:
- strconv包下面的字符串转换因为我们`r.Form`返回的是字符串我们有些时候需要固定的整数就需要使用改包来转换例如Atoi、ParseBool、ParseFloat、ParseInt等函数。
- string包下面的一些过滤函数Trim、ToLower、ToTitle等函数能够获取我们想要的格式信息。
- regexp包来判断一些复杂的需求例如是否是Email、生日之类的
过滤数据除了检查验证之外,还可以在可能时用白名单方法。白名单是指你需要假定你正在检查的数据是非法的,除非你能证明它是合法的。使用这个方法,如果出现错误只会导致把合法的数据当成是非法的,尽管不想犯任何错误,但这样总比把非法数据当成合法数据要安全得多。
##区分过滤数据
如果完成了上面的两步数据过滤的工作就基本完成了但是在编写Web应用的时候我们还需要区分已过滤和被污染数据因为这样可以保证过滤数据的完整性而不影响输入的数据。我们约定把所有经过滤的数据放入一个叫全局的Map变量中(CleanMap)。你需要用两个重要的步骤来防止被污染数据的注入:
- 每个请求都要初始化CleanMap为一个空Map。
- 加入检查及阻止来自外部数据源的变量命名为CleanMap。
接下来为了巩固这些概念,我们通过一个例子来说明这些概念,请看下面这个表单
<form action="/whoami" method="POST">
我是谁:
<select name="name">
<option value="astaxie">astaxie</option>
<option value="herry">herry</option>
<option value="marry">marry</option>
</select>
<input type="submit" />
</form>
在处理这个表单的编程逻辑中非常容易犯的错误是认为只能提交三个选择中的一个。其实攻击可以模拟POST操作递交`name=attack`这样的数据,所以我们在处理的时候需要做类似白名单的处理
r.ParseForm()
name := r.Form.Get("name")
CleanMap := make(map[string]interface{}, 0)
if name == "astaxie" || name == "herry" || name == "marry" {
CleanMap["name"] = name
}
上面代码中我们初始化了一个CleanMap的变量当判断获取的name在astaxie、herry、marry三个之后我们把数据存储到了CleanMap之中这样就可以确保CleanMap["name"]中的数据是合法的从而在代码的其它部分使用它。当然我们还可以在else部分增加非法数据的处理一种可能是再次显示表单并提示错误。但是不要试图为了友好而输出被污染的数据。
上面的方法对于过滤一组已知的合法值的数据很有效,但是对于过滤有一组已知合法字符组成的数据时就没有什么帮助。例如,你可能需要一个用户名只能由字母及数字组成:
r.ParseForm()
username := r.Form.Get("username")
CleanMap := make(map[string]interface{}, 0)
if ok, _ := regexp.MatchString("^[a-zA-Z0-9].$", username); ok {
CleanMap["username"] = username
}
## links
* [目录](<preface.md>)