场景
假设此时有一个用户表,其中每个用户都会有一些随机生成的字符串Token,预访问后面的功能需要先校验请求包里的Token对应的用户身份。
Code
1 | package web |
Gorm 支持使用一个数据库Model指针的形式生成查询语句,比如&User{Token: token},在token的值不为空时,生成的SQL语句将会是:
1 | SELECT * FROM `user` WHERE `token` = 'your-token' LIMIT 1 |
分析
上面代码对于token的校验几乎是形同虚设了,主要原因是 Go 语言的一些特性。
Go 语言中对于变量声明后,存在默认值:
整形如int8、byte、int16、uint、uintprt等,默认值为0。
浮点类型如float32、float64,默认值为0。
布尔类型bool的默认值为false。
字符串string的默认值为”“。
错误类型error的默认值为nil。
但是 Go 语言是无法分辨结构体中某个字符是否被赋值过。例如 token 是一个字符类型,默认赋值为空,如果用户传入的 token 也是空,那么 Go 无法分辨这个 token 值为空是因为声明后自动赋值造成的还是用户输入的就是空字符。
由于是生成的查询语句,如果 token 为空后面内容会被自动忽略,因此 SQL 语句就变成了:
1 | SELECT * FROM `user` LIMIT 1 |
直接会返回第一个用户的信息,一般是管理员的。
所以在查询前一定要进行判断 token 是否为空。
DB.Where(&User{Token: token}).First(&user).Error