开发小同学的骚操作,还好被我发现了

大家好,我是程序员鱼皮。今天给朋友们还原一个我们团队真实的开发场景。

开发现场

最近我们编程导航网站要开发 用户私信 功能,第一期要做的需求很简单:

  1. 能让两个用户之间 1 对 1 单独发送消息
  2. 用户能够查看到消息记录
  3. 用户能够实时收到消息通知

这其实是一个双向实时通讯的场景,显然可以使用 WebSocket 技术来实现。

团队的后端开发小 c 拿到需求后就去调研了,最后打算采用 Spring Boot Starter 快速整合 Websocket 来实现,接受前端某个用户传来的消息后,转发到接受消息的用户的会话,并在数据库中记录,便于用户查看历史。

小 c 的代码写得还是不错的,用了一些设计模式(像策略模式、工厂模式)对代码进行了一些抽象封装。虽然在我看来对目前的需求来说稍微有点过度设计,但开发同学有自己的理由和想法,表示尊重~

前端同学小 L 也很快完成了开发,并且通过了产品的验收。

看似这个需求就圆满地完成了,但直到我阅读前端同学的代码时,才发现了一个 "坑"。

这是前端同学小 L 提交的私信功能代码,看到这里我就已经发现问题了,朋友们能注意到么?

解释一下,小 L 引入了一个 nanoid 库,这个库的作用是生成唯一 id。看到这里,我本能地感到疑惑:为什么要引入这个库?为什么前端要生成唯一 id?

难道。。。是作为私信消息的 id?

果不其然,通过这个库在前端给每个消息生成了一个唯一 id,然后发送给后端。

后端开发的同学可能会想:一般情况下不都是后端利用数据库的自增来生成唯一 id 并返回给前端嘛,怎么需要让前端来生成呢?

这里小 L 的解释是,在本地创建消息的时候,需要有一个 id 来追踪状态,不会出现消息没有 id 的情况。

首先,这么做的确 能够满足需求 ,所以我还是通过了代码审查;但严格意义上来说,让前端来生成唯一 id 其实不够优雅,可能会有一些问题。

前端生成 id 的问题

1)ID 冲突:同时使用系统的前端用户可能是非常多的,每个用户都是一个客户端,多个前端实例可能会生成相同的 ID,导致数据覆盖或混乱。

2)不够安全:切记,前端是没有办法保证安全性的!因为攻击者可以篡改或伪造请求中的数据,比如构造一个已存在的 id,导致原本的数据被覆盖掉,从而破坏数据的一致性。

要做这件事成本非常低,甚至不需要网络攻击方面的知识,打开 F12 浏览器控制台,重放个请求就行实现:

3)时间戳问题:某些生成 id 的算法是依赖时间戳的,比如当前时间不同,生成的 id 就不同。但是如果前端不同用户的电脑时间不一致,就可能会生成重复 id 或无效 id。比如用户 A 电脑是 9 点时生成了 id = 06030901,另一个用户 B 电脑时间比 A 慢了一个小时,现在是 8 点,等用户 B 电脑时间为 9 点的时候,可能又生成了重复 id = 06030901,导致数据冲突。这也被称为 "分布式系统中的全局时钟问题"。

明确前后端职责

虽然 Nanoid 这个库不依赖时间戳来生成 id,不会受到设备时钟不同步的影响,也不会因为时间戳重复而导致 ID 冲突。根据我查阅的资料,生成大约 10 ^ 9 个 ID 后,重复的可能性大约是 10 ^ -17,几乎可以忽略不计。但一般情况下,我个人会更建议将业务逻辑统一放到后端实现,这么做的好处有很多:

  1. 后端更容易保证数据的安全性,可以对数据先进行校验再生成 id
  2. 前端尽量避免进行复杂的计算,而是交给后端,可以提升整体的性能
  3. 职责分离,前端专注于页面展示,后端专注于业务,而不是双方都要维护一套业务逻辑

我举个典型的例子,比如前端下拉框内要展示一些可选项。由于选项的数量并不多,前端当然可以自己维护这些数据(一般叫做枚举值),但后端也会用到这些枚举值,双方都写一套枚举值,就很容易出现不一致的情况。推荐的做法是,让后端返回枚举值给前端,前端不用重复编写。

所以一般情况下,对于 id 的生成,建议统一交给后端实现,可以用雪花算法根据时间戳生成,也可以利用数据库主键生成自增 id 或 UUID,具体需求具体分析吧~


以上就是本期分享,干饭去了 🍚~ 我们私信功能刚上线,估计 Bug 不少,欢迎小伙伴们使用和反馈建议,鱼皮原创的项目教程都在编程导航:code-nav.cn

相关推荐
大杯咖啡15 小时前
localStorage与sessionStorage的区别
前端·javascript
调试人生的显微镜15 小时前
深入剖析 iOS 26 系统流畅度,多工具协同监控与性能优化实践
后端
蹦跑的蜗牛15 小时前
Spring Boot使用Redis实现消息队列
spring boot·redis·后端
RaidenLiu15 小时前
告别陷阱:精通Flutter Signals的生命周期、高级API与调试之道
前端·flutter·前端框架
非凡ghost15 小时前
HWiNFO(专业系统信息检测工具)
前端·javascript·后端
非凡ghost15 小时前
FireAlpaca(免费数字绘图软件)
前端·javascript·后端
大模型教程15 小时前
斩获59.4K星!一款本地部署的开源私人知识库工具
程序员·llm·agent
非凡ghost15 小时前
Sucrose Wallpaper Engine(动态壁纸管理工具)
前端·javascript·后端
拉不动的猪15 小时前
为什么不建议项目里用延时器作为规定时间内的业务操作
前端·javascript·vue.js
间彧15 小时前
从零到一搭建Spring Cloud Alibbaba项目
后端