一、CSP简介
CSP是一种由浏览器支持的HTTP响应头,通过定义一系列规则来严格规定页面中哪些资源(如脚本、样式表、图像等)允许从哪些来源加载。这些规则由一系列指令组成,每个指令都详细描述了特定类型资源的合法来源。如果尝试加载不符合CSP策略的资源,浏览器将阻止这些请求,并在控制台中显示警告或错误信息。
二、CSP的工作原理
CSP通过限制页面可以加载的资源来源,有效减少了恶意脚本执行的机会。当浏览器接收到包含CSP响应头的HTTP响应时,它会检查页面中的每个资源请求是否符合CSP策略。如果某个资源不符合策略,浏览器将阻止该资源的加载,并可能记录相关信息以供后续分析。
三、CSP指令用法
CSP包含多个指令,每个指令都针对特定类型的资源。以下是一些常用的CSP指令及其用法:
default-src
:设置默认的资源加载策略,适用于未明确指定其他指令的资源类型。script-src
:指定脚本资源的合法来源。style-src
:指定样式表资源的合法来源。img-src
:指定图像资源的合法来源。font-src
:指定字体文件的合法来源。connect-src
:指定哪些URL可以用于XMLHttpRequest、WebSocket等连接。object-src
:指定嵌入对象(如<object>
、<embed>
、<applet>
等)的合法来源。media-src
:指定媒体文件(如音频、视频)的合法来源。frame-src
(已弃用,建议使用child-src
):指定嵌入框架(如<iframe>
、<frame>
、<embed>
或<object>
的<param>
标签)的合法来源。注意:frame-src
已被弃用,现代浏览器建议使用child-src
作为替代。child-src
:指定嵌入框架(如<iframe>
)的合法来源。worker-src
:指定Web Worker脚本的合法来源。base-uri
:限制HTML文档中<base>
标签的URL。form-action
:限制表单提交的目标URL。frame-ancestors
:指定哪些页面可以嵌入当前页面(防止点击劫持攻击)。report-uri
:指定一个端点来接收和处理违反CSP策略的报告。
四、具体实例
js
const express = require('express');
const app = express();
const port = 3000;
// 设置CSP响应头
app.use((req, res, next) => {
res.setHeader('Content-Security-Policy', "default-src 'self'; script-src 'self' https://trusted-cdn.com; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src 'self'; object-src 'none';");
next();
});
// 创建一个简单的路由
app.get('/', (req, res) => {
res.send('<h1>Hello, World!</h1><script src="https://untrusted-cdn.com/script.js"></script>');
});
// 启动服务器
app.listen(port, () => {
console.log(`Server is running at http://localhost:${port}/`);
});
在这个例子中,我们使用了一个中间件函数来设置CSP响应头。这个中间件函数会在每个请求被处理之前运行,并设置Content-Security-Policy
响应头。
CSP策略解释
default-src 'self'
:默认资源加载策略为只允许从当前域加载资源。script-src 'self' https://trusted-cdn.com
:允许从当前域和指定的可信CDN(https://trusted-cdn.com
)加载脚本。style-src 'self' 'unsafe-inline'
:允许从当前域加载样式表,并允许内联样式。img-src 'self' data:
:允许从当前域和data URI加载图像。connect-src 'self'
:只允许从当前域进行连接(如XMLHttpRequest、WebSocket等)。object-src 'none'
:不允许加载任何嵌入对象。