作者选择了自由软件基金会作为 写给捐款计划的一部分接受捐款。
介绍
当浏览器加载页面时,它执行大量的代码来渲染内容. 代码可能来自与根文档相同的来源,或不同的来源. 默认情况下,浏览器不会区分两者之间,并执行页面要求的任何代码,而不论来源。 攻击者使用此利用程序来恶意向页面注入脚本,然后执行,因为浏览器没有办法确定内容是否有害。
一个 CSP 是一个 HTTP 标题,它提供了一层额外的安全性,防止代码注入攻击,如 跨网站脚本(XSS), clickjacking和其他类似的利用。它有助于创建一个可信内容的可用列表
,并阻止从允许列表中不存在的来源执行代码。它还向您选择的 URL 报告任何政策违规,以便您可以保持潜在的安全攻击。
使用 CSP 标题,您可以指定网站上内容的批准来源,浏览器可以加载。 任何不来自批准来源的代码将被阻止执行,这使得攻击者难以注入内容和数据。
在本教程中,您将通过实施一个CSP标题(例如Node.js应用程序)(https://github.com/do-community/csp-demo)来审查提供的不同保护,您还将收集CSP违规的JSON报告,以便快速捕捉问题并修复剥削。
前提条件
要遵循本教程,您将需要以下内容:
- 最新版本的 Node.js 已安装在您的计算机上. 按照相关的 如何安装 Node.js 教程的步骤为您的操作系统设置 Node.js 开发环境。
您还应该使用最近的浏览器版本,最好是 Chrome,因为它在写这篇文章时(2020年11月)对 CSP 级别 3 指令提供了最佳的支持。
步骤 1 – 设置 Demo 项目
为了展示创建内容安全政策的过程,我们将通过为此(LINK0)的演示项目(https://github.com/finallyayo/csp-demo)的整个实施过程进行工作。 它是一个单页的网站,具有多种内容,大致相当于典型的网站或应用程序。 它包括一个小型的 Vue.js应用程序, YouTube 嵌入,以及一些来自 Unsplash的图像。 它还使用 Google 字体和 Bootstrap 框架,这是在 [内容交付网络(CDN)]上加载的(https://en.wikipedia.org/wiki/Content_delivery_network)。
在此步骤中,您将在测试服务器或本地机器上设置演示项目,并在浏览器中查看。
首先,使用以下命令将项目克隆到您的文件系统:
1git clone https://github.com/do-community/csp-demo
一旦您的项目目录已设置,请使用以下命令更改它:
1cd csp-demo
接下来,用下一个命令安装package.json
文件中指定的依赖性,您使用express
包来设置 Web 服务器,而nodemon
帮助自动重新启动节点应用程序,当它在目录中检测到文件更改时:
1npm install
一旦依赖已安装依赖,请输入以下命令以在端口 5500
上启动 Web 服务器:
1npm start
您现在可以访问您的浏览器中的your_server_ip:5500
或localhost:5500
,以查看演示页面.您将在页面上找到文本 Hello World!,YouTube嵌入版和一些图像。
在下一节中,我们将实施一个仅涵盖最基本的保护的 CSP 策略,然后在下一节中我们将建立在这一基础上,因为我们揭示了我们需要在页面上允许的所有合法资源。
第2步:实施基本CSP
让我们继续写一个 CSP 策略,限制字体、图像、脚本、风格和嵌入式仅源于当前主机。
1Content-Security-Policy: default-src 'self'; font-src 'self'; img-src 'self'; script-src 'self'; style-src 'self'; frame-src 'self';
以下是本标题中的政策指令的解释:
font-src
定义了可以从哪里加载字体的来源。img-src
定义了允许加载图像的来源。script-src
控制了网页上的任何脚本加载权限。style-src
是允许风格表来源的指令。frame-src
定义了框架嵌入的允许来源。
在本示例中,所有指定的指令在其源列表中都被分配为自我
的关键字,这表明只有来自当前主机的资源(包括 URL 方案和端口号码)才能执行,例如,script-src
允许从当前主机执行脚本,但它阻止了所有其他脚本源。
让我们继续向我们的 Node.js 项目添加标题。
让您的应用程序运行,并打开一个新的终端窗口,以便与您的 server.js
文件工作:
1nano server.js
接下来,从 Express 中间件层中的示例中添加 CSP 标题,以确保您在服务器的每个响应中都包含标题:
1[label server.js]
2const express = require('express');
3const bodyParser = require('body-parser');
4const path = require('path');
5const app = express();
6
7app.use(function (req, res, next) {
8 res.setHeader(
9 'Content-Security-Policy',
10 "default-src 'self'; font-src 'self'; img-src 'self'; script-src 'self'; style-src 'self'; frame-src 'self'"
11 );
12 next();
13});
14
15app.use(bodyParser.json());
16app.use(express.static(path.join(__dirname)));
17
18app.get('/', (req, res) => {
19 res.sendFile(path.join(__dirname + '/index.html'));
20});
21
22const server = app.listen(process.env.PORT || 5500, () => {
23 const { port } = server.address();
24 console.log(`Server running on PORT ${port}`);
25});
保存文件并在浏览器中重新加载项目. 你会注意到页面完全破坏。
我们的 CSP 标题按预期工作,我们在页面上列出的所有外部来源都被阻止加载,因为它们违反了定义的策略,但是,这不是测试全新的策略的理想方式,因为在发生违规时可能会破坏网站。
这就是为什么存在内容安全政策仅报告
标题的原因。您可以使用它而不是内容安全政策
,以防止浏览器执行该策略,同时仍然报告发生的违规行为,这意味着您可以改进该策略而不会危及您的网站。
继续,在您的 server.js 文件中替换内容安全政策
标题为内容安全政策报告仅
:
1nano server.js
添加以下突出的代码:
1[label server.js]
2. . .
3app.use(function (req, res, next) {
4 res.setHeader(
5 'Content-Security-Policy-Report-Only',
6 "default-src 'self'; font-src 'self'; img-src 'self'; script-src 'self'; style-src 'self'; frame-src 'self'"
7 );
8 next();
9});
10. . .
保存文件并在浏览器中重新加载页面. 该页面返回工作状态,但浏览器控制台仍然报告 CSP 违规行为。
在本节中,我们创建了CSP的初始实现,并将其设置为仅报告模式,以便我们可以改进它而不会导致网站破坏。
步骤三:纠正政策违规行为
我们在上一节中实施的策略引发了多个违规行为,因为我们仅限制了所有资源的来源 - 然而,我们在页面上有几个第三方资产。
修复 CSP 违规的两种方法是:批准策略中的来源,或删除触发违规的代码. 由于合法资源正在触发所有违规,我们将在本节中主要关注前者选项。
打开浏览器控制台. 它会显示 CSP 的所有当前违规行为. 让我们解决这些问题。
允许风格表
控制台中的前两次侵犯来自于 Google 字体和 Bootstrap 风格表,您分别从 https://fonts.googleapis.com
和 https://cdn.jsdelivr.net
加载,您可以通过 style-src
指令在页面上允许两者:
1style-src 'self' https://fonts.googleapis.com https://cdn.jsdelivr.net;
这规定了从原始主机的CSS文件, https://fonts.googleapis.com
,和 https://cdn.jsdelivr.net
,应该在页面上执行. 此政策是相当广泛的,因为它允许从允许列表域的任何风格表(不仅仅是你目前正在使用的)。
我们可以更具体地使用我们希望允许的确切文件或目录:
1style-src 'self' https://fonts.googleapis.com https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css;
现在,它只允许准确的,指定的样式表执行. 它将阻止所有其他样式表,即使它们来自 https://cdn.jsdelivr.net
。
您可以更新 CSP 标题,如下所示,更新了 style-src 指令. 到您重新加载页面时,两种违规都将得到解决:
1[label server.js]
2. . .
3app.use(function (req, res, next) {
4 res.setHeader(
5 'Content-Security-Policy-Report-Only',
6 "default-src 'self'; font-src 'self'; img-src 'self'; script-src 'self'; style-src 'self' https://fonts.googleapis.com https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css; frame-src 'self';"
7 );
8 next();
9});
10. . .
允许图像来源
您在页面上使用的图像来自一个单一的来源: https://images.unsplash.com
. 让我们通过以下的 img-src
指令来允许:
1[label server.js]
2. . .
3app.use(function (req, res, next) {
4 res.setHeader(
5 'Content-Security-Policy-Report-Only',
6 "default-src 'self'; font-src 'self'; img-src 'self' https://images.unsplash.com; script-src 'self'; style-src 'self' https://fonts.googleapis.com https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css; frame-src 'self'"
7 );
8 next();
9});
10. . .
允许YouTube嵌入
您可以通过frame-src
指令允许嵌入式浏览环境的有效源,其中使用<iframe>
等元素,如果这个指令不存在,浏览器将寻找child-src
指令,然后返回默认-src
指令。
让我们将https://www.youtube.com
添加到允许列表,以便CSP不会阻止YouTube嵌入式的下载,一旦我们执行政策:
1frame-src 'self' https://www.youtube.com;
如果您有从 https://youtube.com
嵌入的域名,则将根据本政策被阻止,除非您还将 https://youtube.com
添加到允许列表中:
1frame-src 'self' https://www.youtube.com https://youtube.com;
以下是更新后的 CSP 标题. 如下修改frame-src
指令:
1[label server.js]
2. . .
3app.use(function (req, res, next) {
4 res.setHeader(
5 'Content-Security-Policy-Report-Only',
6 "default-src 'self'; font-src 'self'; img-src 'self' https://images.unsplash.com; script-src 'self'; style-src 'self' https://fonts.googleapis.com https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css; frame-src 'self' https://www.youtube.com https://youtube.com;"
7 );
8 next();
9});
10. . .
允许字体文件
Google 字体风格表中包含来自 https://fonts.gstatic.com
的几个字体文件的引用,您会发现这些文件目前违反了定义的 font-src
政策(目前是 self
),因此您需要在修订的政策中考虑这些文件:
1font-src 'self' https://fonts.gstatic.com;
更新 CSP 标题中的font-src
指令如下:
1[label server.js]
2. . .
3app.use(function (req, res, next) {
4 res.setHeader(
5 'Content-Security-Policy-Report-Only',
6 "default-src 'self'; font-src 'self' https://fonts.gstatic.com; img-src 'self' https://images.unsplash.com; script-src 'self'; style-src 'self' https://fonts.googleapis.com https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css; frame-src 'self' https://www.youtube.com https://youtube.com;"
7 );
8 next();
9});
10. . .
重新加载页面后,控制台将不再报告 Google 字体文件的违规情况。
启用 Vue.js 脚本
在 CDN上加载的 Vue.js 脚本正在页面顶部渲染 Hello world! 文本. 我们将允许通过script-src
指令在页面上执行它。
1script-src 'self' https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js;
在本示例中,您只允许该 URL 中的准确脚本在页面上执行. 如果您想在开发和生产构建之间切换,则需要将其他脚本 URL 添加到允许列表中,或者您可以允许在/dist
位置中存在的所有资源同时覆盖两种情况:
1script-src 'self' https://cdn.jsdelivr.net/npm/[email protected]/dist/;
以下是更新后的 CSP 标题,包括相关的更改:
1[label server.js]
2. . .
3app.use(function (req, res, next) {
4 res.setHeader(
5 'Content-Security-Policy-Report-Only',
6 "default-src 'self'; font-src 'self' https://fonts.gstatic.com; img-src 'self' https://images.unsplash.com; script-src 'self' https://cdn.jsdelivr.net/npm/[email protected]/dist/; style-src 'self' https://fonts.googleapis.com https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css; frame-src 'self' https://www.youtube.com https://youtube.com;"
7 );
8 next();
9});
10. . .
此时,我们已成功允许我们页面依赖的所有外部文件和脚本,但我们仍然有另一个 CSP 违规问题要解决,因为页面上有内线脚本。
步骤4 - 处理内部来源
虽然您可以使用不安全的内线
关键字在 CSP 中批准内线代码(如<script>
标签中的JavaScript代码),但它不建议,因为它大大增加了代码注入攻击的风险。
此示例策略允许在页面上执行任何内行脚本,但由于上述原因,这并不安全。
1script-src 'self' 'unsafe-inline' https://unpkg.com/[email protected]/dist/;
避免使用unsafe-inline
的最佳方法是将内线代码移动到外部文件并以这种方式引用它,这是缓存,缩小和可维护的更好的方法,并使CSP在未来更容易修改。
但是,如果您绝对必须使用线程代码,有两种主要方法可以安全地将它们添加到您的许可名单中。
选择1 - 使用一个哈希
此方法要求您计算基于脚本本身的 SHA 哈希,然后将其添加到script-src
指令中。在最近的 Chrome 版本中,您甚至不需要自己生成该哈希,因为它已经包含在控制台中的 CSP 违规错误中:
1[Report Only] Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'self' https://unpkg.com/[email protected]/dist/". Either the 'unsafe-inline' keyword, a hash ('sha256-INJfZVfoUd61ITRFLf63g+S/NJAfswGDl15oK0iXgYM='), or a nonce ('nonce-...') is required to enable inline execution.
这里突出的部分是您需要在script-src
指令中添加的精确的 SHA256 哈希,以允许执行触发违规的特定内线脚本。
复制哈希并将其添加到您的 CSP 如下:
1script-src 'self' https://unpkg.com/[email protected]/dist/ 'sha256-INJfZVfoUd61ITRFLf63g+S/NJAfswGDl15oK0iXgYM=';
这种方法的缺点是,如果脚本的内容发生变化,生成的哈希将是不同的,这将引发违规行为。
选项2 - 使用一个子
允许执行线程代码的第二种方法是使用 nonce. 这些是随机字符串,您可以使用它们来允许一个完整的代码块,无论其内容如何。
以下是使用 nonce 值的例子:
1script-src 'self' https://unpkg.com/[email protected]/dist/ 'nonce-EDNnf03nceIOfn39fn3e9h3sdfa'
CSP 中的 nonce 值必须匹配脚本上的nonce
属性:
1<script nonce="EDNnf03nceIOfn39fn3e9h3sdfa">
2 // Some inline code
3</script>
每当页面被加载时,Nonces 必须是不可磨灭的和动态生成的,以便攻击者无法使用它们执行恶意脚本. 如果您决定实施此选项,则可以使用crypto
包来生成一个Nonce:
1const crypto = require('crypto');
2let nonce = crypto.randomBytes(16).toString('base64');
我们将在本教程中选择哈希方法,因为它对我们的使用案例来说更实用。
在 CSP 标题中更新script-src
指令,以如下所示,包括单个内线脚本的 SHA256 哈希:
1[label server.js]
2. . .
3app.use(function (req, res, next) {
4 res.setHeader(
5 'Content-Security-Policy-Report-Only',
6 "default-src 'self'; font-src 'self' https://fonts.gstatic.com; img-src 'self' https://images.unsplash.com; script-src 'self' https://unpkg.com/[email protected]/dist/ 'sha256-INJfZVfoUd61ITRFLf63g+S/NJAfswGDl15oK0iXgYM='; style-src 'self' https://fonts.googleapis.com https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css; frame-src 'self' https://www.youtube.com https://youtube.com;"
7 );
8 next();
9});
10. . .
这将删除内线脚本从控制台中触发的最终 CSP 违规错误。
在下一节中,我们将监测我们的CSP在生产环境中的影响。
步骤五:监控违规行为
例如,如果您忘记允许一个合法的来源在生产中,或者当攻击者试图利用XSS攻击引擎(您需要立即识别并停止)。
没有某种形式的积极报告,没有办法知道这些事件,这就是为什么报告到
指令存在. 它指定一个位置,浏览器应该发布一个JSON格式的违规报告,如果它必须采取行动基于CSP。
要使用此指令,您需要添加一个额外的标题来指定 报告 API的终端点:
1Report-To: {"group":"csp-endpoint","max_age":10886400,"endpoints":[{"url":"http://your_server_ip:5500/__cspreport__"}],"include_subdomains":true}
一旦设置,请在报告到
指令中指定组名称如下:
1report-to csp-endpoint;
以下是server.js
文件的更改部分,请确保在Report-To
标题中用您的实际服务器 IP 地址更换<your_server_ip>
位置:
1[label server.js]
2. . .
3app.use(function (req, res, next) {
4 res.setHeader(
5 'Report-To',
6 '{"group":"csp-endpoint","max_age":10886400,"endpoints":[{"url":"https://<your_server_ip>:5500/__cspreport__"}],"include_subdomains":true}'
7 );
8 res.setHeader(
9 'Content-Security-Policy-Report-Only',
10 "default-src 'self'; font-src 'self' https://fonts.gstatic.com; img-src 'self' https://images.unsplash.com; script-src 'self' https://cdn.jsdelivr.net/npm/[email protected]/dist/ 'sha256-INJfZVfoUd61ITRFLf63g+S/NJAfswGDl15oK0iXgYM='; style-src 'self' https://fonts.googleapis.com https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css; frame-src 'self' https://www.youtube.com https://youtube.com; report-to csp-endpoint;"
11 );
12 next();
13});
14. . .
报告到
指令旨在取代现已废弃的报告到
指令,但大多数浏览器尚未支持它(截至2020年11月)。因此,为了与当前浏览器的兼容性,同时确保与未来的浏览器发布支持的兼容性,您应该在您的 CSP 中指定报告到
和报告到
。
1[label server.js]
2. . .
3app.use(function (req, res, next) {
4 res.setHeader(
5 'Report-To',
6 '{"group":"csp-endpoint","max_age":10886400,"endpoints":[{"url":"https://your_server_ip:5500/__cspreport__"}],"include_subdomains":true}'
7 );
8 res.setHeader(
9 'Content-Security-Policy-Report-Only',
10 "default-src 'self'; font-src 'self' https://fonts.gstatic.com; img-src 'self' https://images.unsplash.com; script-src 'self' https://cdn.jsdelivr.net/npm/[email protected]/dist/ 'sha256-INJfZVfoUd61ITRFLf63g+S/NJAfswGDl15oK0iXgYM='; style-src 'self' https://fonts.googleapis.com https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css; frame-src 'self' https://www.youtube.com https://youtube.com; report-to csp-endpoint; report-uri /__cspreport__;"
11 );
12 next();
13});
14. . .
/__cspreport__
路径也需要存在于服务器上;添加到您的文件中如下:
1[label server.js]
2. . .
3app.get('/', (req, res) => {
4 res.sendFile(path.join(__dirname + '/index.html'));
5});
6
7app.post('/__cspreport__', (req, res) => {
8 console.log(req.body);
9});
10. . .
有些浏览器将报告的内容类型
发送为应用程序/csp-report
,而其他浏览器则使用应用程序/json
。
要计算所有可能的内容类型
值,您必须在您的快递服务器上设置一些配置:
1[label server.js]
2. . .
3app.use(
4 bodyParser.json({
5 type: ['application/json', 'application/csp-report', 'application/reports+json'],
6 })
7);
8. . .
在此时,任何 CSP 违规行为将被发送到 /__cspreport__
路线,并随后登录到终端。
您可以通过添加不符合当前 CSP 的源资源来尝试,或者如下所示修改index.html
文件中的内线脚本:
1[label index.html]
2. . .
3<script>
4 new Vue({
5 el: '#vue',
6 render(createElement) {
7 return createElement('h1', 'Hello World!');
8 },
9 });
10 console.log("Hello")
11</script>
12. . .
这会引发违规,因为脚本的哈希现在与您在CSP标题中所包含的不同。
以下是使用report-uri
的浏览器的典型违规报告:
1{
2 'csp-report': {
3 'document-uri': 'http://localhost:5500/',
4 referrer: '',
5 'violated-directive': 'script-src-elem',
6 'effective-directive': 'script-src-elem',
7 'original-policy': "default-src 'self'; font-src 'self' https://fonts.gstatic.com; img-src 'self' https://images.unsplash.com; script-src 'self' https://cdn.jsdelivr.net/npm/[email protected]/dist/ 'sha256-INJfZVfoUd61ITRFLf63g+S/NJAfswGDl15oK0iXgYM='; style-src 'self' https://fonts.googleapis.com https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css; frame-src 'self' https://www.youtube.com https://youtube.com; report-uri /__cspreport__;",
8 disposition: 'report',
9 'blocked-uri': 'inline',
10 'line-number': 58,
11 'source-file': 'http://localhost:5500/',
12 'status-code': 200,
13 'script-sample': ''
14 }
15}
本报告的部分是:
document-uri
:侵权发生的页面.referrer
: 该页面的引用者.blocked-uri
: 侵犯该页面策略的资源(在这种情况下是inline
脚本)。line-number
: 内线代码开始的行编号.violated-directive
: 被侵犯的特定指令. (在这种情况下是script-src-elem
)original-policy
: 页面的完整政策。
如果浏览器支持报告到
指令,则实用负载应具有与以下相似的结构. 注意它与报告到
实用负载如何不同,同时仍然携带相同的信息:
1[{
2 "age": 16796,
3 "body": {
4 "blocked-uri": "https://vimeo.com",
5 "disposition": "enforce",
6 "document-uri": "https://localhost:5500/",
7 "effective-directive": "frame-src",
8 "line-number": 58,
9 'original-policy': "default-src 'self'; font-src 'self' https://fonts.gstatic.com; img-src 'self' https://images.unsplash.com; script-src 'self' https://cdn.jsdelivr.net/npm/[email protected]/dist/ 'sha256-INJfZVfoUd61ITRFLf63g+S/NJAfswGDl15oK0iXgYM='; style-src 'self' https://fonts.googleapis.com https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css; frame-src 'self' https://www.youtube.com https://youtube.com; report-uri /__cspreport__;",
10 "referrer": "",
11 "script-sample": "",
12 "sourceFile": "https://localhost:5500/",
13 "violated-directive": "frame-src"
14 },
15 "type": "csp",
16 "url": "https://localhost:5500/",
17 "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36"
18}]
<$>[注]
注:报告到
指令仅在安全环境中得到支持,这意味着您需要用有效的 HTTPS 证书设置 Express 服务器,否则您将无法测试或使用它。
在本节中,我们成功地在我们的服务器上设置了CSP监控,以便我们能够快速检测和修复问题。
步骤 6 – 发布最终政策
一旦您确信 CSP 已正确设置(理想情况下,在仅在报告模式下运行几天或几周后),您可以通过将 CSP 标题从内容安全政策报告仅
更改为内容安全政策
来执行。
除了报告违规行为外,这还会阻止未经授权的资源在页面上运行,从而为您的访问者提供更安全的体验。
以下是「server.js」文件的最终版本:
1[label server.js]
2const express = require('express');
3const bodyParser = require('body-parser');
4const path = require('path');
5const app = express();
6
7app.use(function (req, res, next) {
8 res.setHeader(
9 'Report-To',
10 '{"group":"csp-endpoint","max_age":10886400,"endpoints":[{"url":"http://your_server_ip:5500/__cspreport__"}],"include_subdomains":true}'
11 );
12 res.setHeader(
13 'Content-Security-Policy',
14 "default-src 'self'; font-src 'self' https://fonts.gstatic.com; img-src 'self' https://images.unsplash.com; script-src 'self' https://cdn.jsdelivr.net/npm/[email protected]/dist/ 'sha256-INJfZVfoUd61ITRFLf63g+S/NJAfswGDl15oK0iXgYM='; style-src 'self' https://fonts.googleapis.com https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css; frame-src 'self' https://www.youtube.com https://youtube.com; report-to csp-endpoint; report-uri /__cspreport__;"
15 );
16 next();
17});
18
19app.use(
20 bodyParser.json({
21 type: [
22 'application/json',
23 'application/csp-report',
24 'application/reports+json',
25 ],
26 })
27);
28app.use(express.static(path.join(__dirname)));
29
30app.get('/', (req, res) => {
31 res.sendFile(path.join(__dirname + '/index.html'));
32});
33
34app.post('/__cspreport__', (req, res) => {
35 console.log(req.body);
36});
37
38const server = app.listen(process.env.PORT || 5500, () => {
39 const { port } = server.address();
40 console.log(`Server running on PORT ${port}`);
41});
<$>[注]
浏览器支持
CSP 标题是 在所有浏览器中支持 除了 Internet Explorer,它使用非标准的X-Content-Security-Policy
标题。
最新版本的 CSP 规范( 3 级)(https://www.w3.org/TR/CSP3/)也引入了一些较新的指令,这些指令目前没有得到很好的支持。 示例包括script-src-elem
和prefetch-src
指令。
结论
在本文中,您为 Node.js 应用程序设置了有效的内容安全策略,并监控了违规行为. 如果您有较旧或更复杂的网站,则需要更广泛的策略设置,涵盖所有基础。
您可以找到本教程的最终代码在 这个GitHub存储库。
有关安全的更多文章,请参阅我们的 安全主题页面。如果您想了解有关使用 Node.js 的更多信息,您可以阅读我们的 如何在 Node.js 系列中编码 。