Python技术迷

用户取用户名为 null,害我熬夜查到两点。。

程序员都懂,null 这个东西,它不是空,它也不是字符串 "null",它是……一种可以毁天灭地的存在

事情是这样的。我们组一个新来的同事,开发一个新用户注册功能。这个功能其实很简单,用户名、密码、邮箱,注册完写入数据库,没啥难度。Z写得飞快,提交PR还挺干净,我一看觉得没啥问题就合了。谁能想到,几天之后测试组给我们提了个bug,说有个账号登录总是异常,而且日志里一大堆NullPointerException……

Image

我当时心里咯噔一下,直觉告诉我这肯定跟那个用户名是null的用户有关。查数据库一看,用户名字段居然真的有一条是null。好家伙,这下乐子大了。

你可能会问,怎么可能注册成功一个用户名为null的用户呢?咱们来看代码。

defcreate_user(username, password):
ifnot username:
raise ValueError("用户名不能为空")
    save_to_db(username, password)

Z写的这段逻辑看着好像没啥问题,关键就在于那句 if not username: ——你以为它能挡住所有非法输入,但其实,这里只挡住了空字符串 ""、None,还有一些Falsy值,比如0、False啥的。但问题是,Z是怎么拿到这个username的?是通过HTTP请求体的JSON字段,长这样:

{
"username": null,
"password": "123456"
}

null在JSON里是个特殊值,Python解析成None没问题,但如果你不明确判断是否是None,它可能就默默混过去了。关键是——我们当时的验证逻辑,是在前端做的,没在后端做二次校验 🤡

更刺激的是,我们系统内部有一堆逻辑,拿用户名当key,比如:

user_map[username] = get_user_data(username)

你敢信这玩意儿里塞进了个None当key?然后一查日志,果然:

TypeError: unhashable type: 'NoneType'

更惨的是登录的时候,有个log写法是这样的:

print("用户登录:" + username)

这也出问题了——None和字符串拼接?好耶:

TypeError: can only concatenate str (not "NoneType") to str

我一边看日志一边骂娘:这bug要是再不修,我就要背锅了……

于是我通宵查到底是谁创建了这个用户,最后发现——注册接口压根没限制这个字段不能为null。你们懂这意味着什么吗?只要前端传个null,不会报错就能混进数据库。

赶紧给Z发消息,Z说:“我当时测试的时候前端都传了字符串啊,没考虑过有人直接curl提交 null 字段……”

兄弟,互联网是没有尽头的,总有人会做你想不到的事。

然后我们临时加了个修复补丁,强制判断username类型必须是字符串,不能是None:

defcreate_user(username, password):
ifnot isinstance(username, str) ornot username.strip():
raise ValueError("非法用户名")
    save_to_db(username, password)

补完之后终于安心了。

你以为没人会特地注册个null用户名?呵呵,别说null了,还有人用SQL注入当用户名试图搞事情呢。

而且 null 这个坑,在不同语言里表现还不一样。Python 里是 None,Java 里是 Null,JS 里有 null 还有 undefined——每一个都是曾经让无数程序员熬夜到秃头的存在 🫠

对了,我后来在B站还看了个段子,说有个程序员注册用户名是 "undefined",然后产品经理看报表问他为啥有一堆“未定义用户”……

我:。。。

所以说,验证逻辑永远不要只靠前端,后端一定要做兜底。类型检查、边界判断、字段非空校验,一个都不能少。不然哪天又遇到个喜欢当黑客的“天才用户”,你可能又得从晚上查到天亮。 你们遇到过更离谱的输入吗?来评论区聊聊,咱们比比谁更惨

最后,我为大家打造了一份deepseek的入门到精通教程,完全免费:https://www.songshuhezi.com/deepseek

也可以看我写的这篇文章《DeepSeek满血复活,直接起飞!》来进行本地搭建。

对编程、职场感兴趣的同学,大家可以联系我微信:golang404,拉你进入“程序员交流群”。
🔥虎哥私藏精品 热门推荐🔥

虎哥作为一名老码农,整理了全网最全《python高级架构师资料合集》。

资料包含了《IDEA视频教程》、《最全python面试题库》、《最全项目实战源码及视频》及《毕业设计系统源码》,总量高达650GB,全部免费领取