宇宙纪元

hinder110 的思考、读书与代码札记。

0%

给 yueduqi 写后端的收获

JWT 认证

登录时用 bcrypt 比密码——这是一次性的。登录后每次请求带 token,后端用 JWT_SECRET 验签名判断真伪。

和密码哈希的区别:bcrypt 需要查数据库比对;JWT 验签不需要,纯数学计算,快。

数据建模两层思维

第一层:实体建表——users、books。

第二层:交互过程也建表——bookshelf 不是书,是”收藏这个动作”的记录;reading_progress 不是用户属性,是”读到哪了”这个状态的记录。

upsert 原子操作

INSERT ... ON CONFLICT DO UPDATE 是一条不可打断的 SQL。

先 SELECT 再 UPDATE 的问题:两个请求同时查,都认为”没有记录”,同时 INSERT,第二个就报错。upsert 把判断和执行合成原子操作,数据库内部排队处理,冲突自动变更新。

统一响应格式

前后端约定 { success, data, error } 格式。前端不用处理 HTTP 状态码,所有异常在 request 函数内部统一转化。调用方只关心 success 是 true 还是 false。

好处:TypeScript 类型安全,不用每次都处理低级的异常分支。

输入白名单

用户传的 source 参数只允许三个值,其余全给默认值。不信任任何用户输入,只放行明确安全的。

原则:与其判断什么是危险的,不如只允许那些确认安全的。

token 存 localStorage

localStorage 是浏览器端的简单持久化键值存储,刷新页面不丢。和 PostgreSQL 的区别——localStorage 是客户端个人状态,数据库是服务端全体数据。

前后端完整数据流

1
用户操作 → api.ts 发 fetch → Express 路由 → 数据库读写 → JSON 返回 → React state → UI 刷新

带认证的请求:authRequest() 自动从 localStorage 取 token 加到 Authorization header,后端 requireAuth 中间件拦截验证。

记住

  • 类型约束比记性好
  • 原子操作比先查后改安全
  • 白名单比黑名单可靠
  • 约定统一格式比每次处理异常省代码