内容安全策略
什么是 CSP?
内容安全策略(CSP) 是一种增加的安全层,有助于检测和缓解某些类型的攻击,包括跨站脚本(XSS)和数据注入攻击。这些攻击可用于从数据盗窃到网站篡改,再到恶意软件分发。
集成步骤
添加路由插件
要将中间件插件添加到您的应用程序中,只需在 routes 文件夹中添加一个名为 plugin@your-plugin-name.ts
的文件。
该文件将在每个请求中加载,允许您添加标头、修改响应等。
添加插件
src/
└── routes/
├── plugin@csp.ts # 在每个请求上运行的插件(路由中间件)
├── contact/
│ └── index.mdx # https://example.com/contact
├── about/
│ └── index.md # https://example.com/about
├── index.mdx # https://example.com/
│
└── layout.tsx # 用于所有页面的布局
示例
此模板提供了非常宽松的向后兼容默认值。 强烈建议您根据自己的特定用例进行自定义。 由于这是一个高级主题,您应该仔细阅读 MDN 或 web.dev,以更好地理解 CSP。 请注意,在开发模式下,Vite 脚本没有 nonce,并且会报告错误。因此,示例不会在开发模式下添加 csp。
src/routes/plugin@csp.ts
import type { RequestHandler } from "@builder.io/qwik-city";
import { isDev } from "@builder.io/qwik/build";
export const onRequest: RequestHandler = event => {
if (isDev) return; // 在开发模式下不返回 CSP 标头
const nonce = Date.now().toString(36); // 在此处添加您的自定义 nonce 逻辑
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("; "));
};
同样添加到 Service Worker
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 "./global.css";
export default component$(() => {
const nonce = useServerData<string | undefined>("nonce");
return (
<QwikCityProvider>
<head>
<meta charSet="utf-8" />
<link rel="manifest" href="/manifest.json" />
<RouterHead />
</head>
<body lang="en">
<RouterOutlet />
<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/