内容安全策略
什么是 CSP?
内容安全策略 (CSP) 是一种额外的安全层,有助于检测和缓解某些类型的攻击,包括跨站点脚本 (XSS) 和数据注入攻击。这些攻击被用于从数据窃取到网站篡改,再到恶意软件分发等各种目的。
集成步骤
添加路由插件
要将中间件插件添加到您的应用程序,只需在路由文件夹中添加一个名为 [email protected]
的文件。此文件将在每次请求时加载,允许您添加标头、修改响应等等。
添加插件
src/
└── routes/
├── [email protected] # The plugin which runs on every request (route middleware)
├── contact/
│ └── index.mdx # https://example.com/contact
├── about/
│ └── index.md # https://example.com/about
├── index.mdx # https://example.com/
│
└── layout.tsx # This layout is used for all pages
示例
此模板提供了非常宽松的向后兼容默认值。强烈建议您根据您的具体用例对其进行自定义。由于这是一个高级主题,您应该仔细查看 MDN 或 web.dev 以更好地了解 CSP。请注意,在开发模式下,Vite 脚本没有 nonce 并且会报告。因此,此示例在开发模式下不会添加 csp。
src/routes/[email protected]
import type { RequestHandler } from "@builder.io/qwik-city";
import { isDev } from "@builder.io/qwik/build";
export const onRequest: RequestHandler = event => {
if (isDev) return; // Will not return CSP headers in dev mode
const nonce = Date.now().toString(36); // Your custom nonce logic here
event.sharedMap.set("@nonce", nonce);
const csp = [
`default-src 'self' 'unsafe-inline'`,
`font-src 'self'`,
`img-src 'self' 'unsafe-inline' data:`,
`script-src 'self' 'unsafe-inline' https: 'nonce-${nonce}' 'strict-dynamic'`,
`style-src 'self' 'unsafe-inline'`,
`frame-src 'self' 'nonce-${nonce}'`,
`object-src 'none'`,
`base-uri 'self'`,
];
event.headers.set("Content-Security-Policy", csp.join("; "));
};
也将其添加到服务工作者中
src/root.ts
import { component$, useServerData } from "@builder.io/qwik";
import {
QwikCityProvider,
RouterOutlet,
ServiceWorkerRegister,
} from "@builder.io/qwik-city";
import { RouterHead } from "./components/router-head/router-head";
import { isDev } from "@builder.io/qwik/build";
import "./global.css";
export default component$(() => {
const nonce = useServerData<string | undefined>("nonce");
return (
<QwikCityProvider>
<head>
<meta charSet="utf-8" />
{!isDev && <link rel="manifest" href={`${import.meta.env.BASE_URL}manifest.json`} />}
<RouterHead />
</head>
<body lang="en">
<RouterOutlet />
{!isDev && <ServiceWorkerRegister nonce={nonce} />}
</body>
</QwikCityProvider>
);
});
自定义脚本
如果您需要添加 nonce 的自定义脚本标签,可以使用 useServerData
钩子从服务器获取 nonce 并将其添加到您的脚本标签中。
src/components/some-component.tsx
export default component$(() => {
const nonce = useServerData<string | undefined>("nonce");
return (
<div>
<script nonce={nonce}>alert("Hello world")</script>
</div>
);
});
验证您的 CSP
有一个很棒的工具可以验证您的 CSP:https://csp-evaluator.withgoogle.com/