1.7 KiB
1.7 KiB
title, impact, impactDescription, tags
| title | impact | impactDescription | tags |
|---|---|---|---|
| Avoid Shared Module State for Request Data | HIGH | 防止并发 bug 和请求数据泄漏 | server, rsc, ssr, concurrency, security, state |
避免为请求数据使用共享模块状态
对于 React Server Components 以及在 SSR 期间渲染的客户端组件,应避免使用可变的模块级变量来共享请求范围内的数据。服务端渲染可以在同一进程中并发执行。如果一个渲染向共享模块状态写入数据,而另一个渲染读取该状态,就可能出现竞态条件、跨请求污染以及安全漏洞,导致一个用户的数据出现在另一个用户的响应中。
请将服务端的模块作用域视为进程级的共享内存,而非请求局部状态。
错误做法(请求数据在并发渲染间泄漏):
let currentUser: User | null = null
export default async function Page() {
currentUser = await auth()
return <Dashboard />
}
async function Dashboard() {
return <div>{currentUser?.name}</div>
}
如果两个请求重叠,请求 A 可以设置 currentUser,然后请求 B 在请求 A 完成渲染 Dashboard 之前将其覆盖。
正确做法(将请求数据保持在渲染树局部):
export default async function Page() {
const user = await auth()
return <Dashboard user={user} />
}
function Dashboard({ user }: { user: User | null }) {
return <div>{user?.name}</div>
}
安全例外情况:
- 在模块作用域一次性加载的不可变静态资源或配置
- 有意设计为跨请求复用且键值正确的共享缓存
- 不存储请求或用户特定可变数据的进程级单例
关于静态资源和配置,请参见 Hoist Static I/O to Module Level。