taint
用法
¥Usage
taint
选项支持实验性的 React API,用于污染对象和值。此功能有助于防止敏感数据意外传递给客户端。启用后,你可以使用:
¥The taint
option enables support for experimental React APIs for tainting objects and values. This feature helps prevent sensitive data from being accidentally passed to the client. When enabled, you can use:
experimental_taintObjectReference
污染对象引用。¥
experimental_taintObjectReference
taint objects references.experimental_taintUniqueValue
用于污染唯一值。¥
experimental_taintUniqueValue
to taint unique values.
需要了解:激活此标志还会为
app
目录启用 Reactexperimental
通道。¥Good to know: Activating this flag also enables the React
experimental
channel forapp
directory.
import type { NextConfig } from 'next'
const nextConfig: NextConfig = {
experimental: {
taint: true,
},
}
export default nextConfig
警告:不要依赖污点 API 作为防止敏感数据暴露给客户端的唯一机制。查看我们的 安全建议。
¥Warning: Do not rely on the taint API as your only mechanism to prevent exposing sensitive data to the client. See our security recommendations.
污点 API 允许你通过声明式显式标记不允许通过服务器-客户端边界的数据来采取防御措施。当对象或值跨越服务器-客户端边界时,React 会抛出错误。
¥The taint APIs allows you to be defensive, by declaratively and explicitly marking data that is not allowed to pass through the Server-Client boundary. When an object or value, is passed through the Server-Client boundary, React throws an error.
这在以下情况下很有用:
¥This is helpful for cases where:
读取数据的方法不受你控制
¥The methods to read data are out of your control
你必须处理未由你定义的敏感数据形状。
¥You have to work with sensitive data shapes not defined by you
服务器组件渲染期间会访问敏感数据
¥Sensitive data is accessed during Server Component rendering
建议对数据和 API 进行建模,以免敏感数据返回到不需要的上下文。
¥It is recommended to model your data and APIs so that sensitive data is not returned to contexts where it is not needed.
注意事项
¥Caveats
污染只能通过引用跟踪对象。复制对象会创建一个未受污染的版本,这将失去 API 提供的所有保证。你需要污染副本。
¥Tainting can only keep track of objects by reference. Copying an object creates an untainted version, which loses all guarantees given by the API. You'll need to taint the copy.
污染无法跟踪从受污染值派生的数据。你还需要污染派生值。
¥Tainting cannot keep track of data derived from a tainted value. You also need to taint the derived value.
只要值的生命周期引用在作用域内,它们就会受到污染。有关更多信息,请参阅
experimental_taintUniqueValue
参数参考。¥Values are tainted for as long as their lifetime reference is within scope. See the
experimental_taintUniqueValue
parameters reference, for more information.
示例
¥Examples
污染对象引用
¥Tainting an object reference
在本例中,getUserDetails
函数返回给定用户的数据。我们会污染用户对象引用,使其无法跨越服务器-客户端边界。例如,假设 UserCard
是客户端组件。
¥In this case, the getUserDetails
function returns data about a given user. We taint the user object reference, so that it cannot cross a Server-Client boundary. For example, assuming UserCard
is a Client Component.
import { experimental_taintObjectReference } from 'react'
function getUserDetails(id: string): UserDetails {
const user = await db.queryUserById(id)
experimental_taintObjectReference(
'Do not use the entire user info object. Instead, select only the fields you need.',
user
)
return user
}
我们仍然可以访问受污染的 userDetails
对象中的各个字段。
¥We can still access individual fields from the tainted userDetails
object.
export async function ContactPage({
params,
}: {
params: Promise<{ id: string }>
}) {
const { id } = await params
const userDetails = await getUserDetails(id)
return (
<UserCard
firstName={userDetails.firstName}
lastName={userDetails.lastName}
/>
)
}
现在,将整个对象传递给客户端组件将抛出错误。
¥Now, passing the entire object to the Client Component will throw an error.
export async function ContactPage({
params,
}: {
params: Promise<{ id: string }>
}) {
const userDetails = await getUserDetails(id)
// Throws an error
return <UserCard user={userDetails} />
}
污染唯一值
¥Tainting a unique value
在本例中,我们可以通过等待对 config.getConfigDetails
的调用来访问服务器配置。但是,系统配置包含我们不想暴露给客户端的 SERVICE_API_KEY
。
¥In this case, we can access the server configuration by awaiting calls to config.getConfigDetails
. However, the system configuration contains the SERVICE_API_KEY
that we don't want to expose to clients.
我们可以污染 config.SERVICE_API_KEY
的值。
¥We can taint the config.SERVICE_API_KEY
value.
import { experimental_taintUniqueValue } from 'react'
function getSystemConfig(): SystemConfig {
const config = await config.getConfigDetails()
experimental_taintUniqueValue(
'Do not pass configuration tokens to the client',
config,
config.SERVICE_API_KEY
)
return config
}
我们仍然可以访问 systemConfig
对象的其他属性。
¥We can still access other properties of the systemConfig
object.
export async function Dashboard() {
const systemConfig = await getSystemConfig()
return <ClientDashboard version={systemConfig.SERVICE_API_VERSION} />
}
但是,将 SERVICE_API_KEY
传递给 ClientDashboard
会引发错误。
¥However, passing SERVICE_API_KEY
to ClientDashboard
throws an error.
export async function Dashboard() {
const systemConfig = await getSystemConfig()
// Someone makes a mistake in a PR
const version = systemConfig.SERVICE_API_KEY
return <ClientDashboard version={version} />
}
请注意,即使如此,systemConfig.SERVICE_API_KEY
仍会被重新赋值给一个新变量。将其传递给客户端组件仍然会抛出错误。
¥Note that, even though, systemConfig.SERVICE_API_KEY
is reassigned to a new variable. Passing it to a Client Component still throws an error.
然而,从受污染的唯一值派生的值将暴露给客户端。
¥Whereas, a value derived from a tainted unique value, will be exposed to the client.
export async function Dashboard() {
const systemConfig = await getSystemConfig()
// Someone makes a mistake in a PR
const version = `version::${systemConfig.SERVICE_API_KEY}`
return <ClientDashboard version={version} />
}
更好的方法是从 getSystemConfig
返回的数据中删除 SERVICE_API_KEY
。
¥A better approach is to remove SERVICE_API_KEY
from the data returned by getSystemConfig
.