taintUniqueValue
可讓您防止將密碼、金鑰或權杖等唯一值傳遞給客戶端元件。
taintUniqueValue(errMessage, lifetime, value)
若要防止傳遞包含敏感資料的物件,請參閱 taintObjectReference
。
參考
taintUniqueValue(message, lifetime, value)
使用密碼、權杖、金鑰或雜湊呼叫 taintUniqueValue
,將其註冊到 React 中,使其不被允許按原樣傳遞到客戶端
import {experimental_taintUniqueValue} from 'react';
experimental_taintUniqueValue(
'Do not pass secret keys to the client.',
process,
process.env.SECRET_KEY
);
參數
-
message
:如果將value
傳遞給客戶端元件,您想要顯示的訊息。如果將value
傳遞給客戶端元件,則此訊息將作為拋出錯誤的一部分顯示。 -
lifetime
:任何指示value
應該被污染多長時間的物件。當此物件仍然存在時,value
將被阻止傳送到任何客戶端元件。例如,傳遞globalThis
會在應用程式的生命週期內封鎖該值。lifetime
通常是一個其屬性包含value
的物件。 -
value
:字串、bigint 或 TypedArray。value
必須是具有高熵的唯一字元或位元組序列,例如加密權杖、私鑰、雜湊或長密碼。value
將被阻止傳送到任何客戶端元件。
回傳值
experimental_taintUniqueValue
會回傳 undefined
。
注意事項
- 從受污染的值衍生新的值可能會損害污染保護。透過將受污染的值轉換為大寫、將受污染的字串值串接成更大的字串、將受污染的值轉換為 base64、取得受污染值的子字串以及其他類似的轉換所建立的新值,除非您明確地在這些新建立的值上呼叫
taintUniqueValue
,否則它們不會被污染。 - 不要使用
taintUniqueValue
來保護低熵值,例如 PIN 碼或電話號碼。如果請求中的任何值是由攻擊者控制的,他們可以透過列舉機密的可能值來推斷哪個值受到污染。
用法
防止 Token 傳遞到客戶端組件
為了確保敏感資訊(例如密碼、會話 Token 或其他唯一值)不會意外傳遞到客戶端組件,taintUniqueValue
函式提供了一層保護。當一個值被標記為受污染時,任何嘗試將其傳遞到客戶端組件的操作都將導致錯誤。
lifetime
參數定義了值保持受污染狀態的持續時間。對於應永久保持受污染狀態的值,可以使用像 globalThis
或 process
之類的物件作為 lifetime
參數。這些物件的生命週期涵蓋應用程式執行的整個期間。
import {experimental_taintUniqueValue} from 'react';
experimental_taintUniqueValue(
'Do not pass a user password to the client.',
globalThis,
process.env.SECRET_KEY
);
如果受污染值的壽命與物件綁定,則 lifetime
參數應為封裝該值的物件。這可確保受污染的值在封裝物件的整個生命週期中保持受保護狀態。
import {experimental_taintUniqueValue} from 'react';
export async function getUser(id) {
const user = await db`SELECT * FROM users WHERE id = ${id}`;
experimental_taintUniqueValue(
'Do not pass a user session token to the client.',
user,
user.session.token
);
return user;
}
在此範例中,user
物件作為 lifetime
參數。如果此物件儲存在全域快取中或可被另一個請求存取,則會話 Token 將保持受污染狀態。
深入探討
如果您正在執行的伺服器組件環境可以存取私鑰或密碼(例如資料庫密碼),則必須小心不要將其傳遞給客戶端組件。
export async function Dashboard(props) {
// DO NOT DO THIS
return <Overview password={process.env.API_PASSWORD} />;
}
"use client";
import {useEffect} from '...'
export async function Overview({ password }) {
useEffect(() => {
const headers = { Authorization: password };
fetch(url, { headers }).then(...);
}, [password]);
...
}
此範例會將機密 API Token 洩漏給客戶端。如果此 API Token 可用於存取此特定使用者不應存取的資料,則可能導致資料外洩。
理想情況下,此類機密應抽象化到一個單獨的輔助程式檔案中,該檔案只能由伺服器上受信任的資料工具匯入。甚至可以使用 server-only
標記該輔助程式,以確保此檔案不會在客戶端上匯入。
import "server-only";
export function fetchAPI(url) {
const headers = { Authorization: process.env.API_PASSWORD };
return fetch(url, { headers });
}
有時在重構過程中會發生錯誤,而且並非所有同事都知道這一點。為了防止日後發生此類錯誤,我們可以「污染」實際的密碼
import "server-only";
import {experimental_taintUniqueValue} from 'react';
experimental_taintUniqueValue(
'Do not pass the API token password to the client. ' +
'Instead do all fetches on the server.'
process,
process.env.API_PASSWORD
);
現在,每當有人嘗試將此密碼傳遞給客戶端組件,或使用伺服器函式將密碼傳送給客戶端組件時,系統都會拋出一個錯誤,並顯示您在呼叫 taintUniqueValue
時定義的訊息。