spaze / csp-config
从配置文件构建内容安全策略
Requires
- php: ^8.2
- nette/di: ^3.1
- nette/schema: ^1.2
- spaze/nonce-generator: ^4.0
Requires (Dev)
- nette/bootstrap: ^3.2
- nette/tester: ^2.5
- php-parallel-lint/php-console-highlighter: ^1.0
- php-parallel-lint/php-parallel-lint: ^1.3
- phpstan/phpstan: ^1.10
- spaze/coding-standard: ^1.6
Suggests
- spaze/sri-macros: For script tags with automatically added nonces, and Subresource Integrity hashes, too
README
从配置文件构建内容安全策略。支持按页面或模块设置不同的策略,并在需要时可以动态添加片段。
此库旨在与任何框架(或无需框架)一起使用,但附带一个Nette 框架的桥梁。
请注意,此库仅构建头部值,您仍然需要自己发送头部!
安装
安装库的最佳方式是使用 Composer
composer require spaze/csp-config
Nette 框架配置
如果您使用 Nette 框架,可以将扩展添加到您的配置文件中
extensions: contentSecurityPolicy: Spaze\ContentSecurityPolicy\Bridges\Nette\CspConfigExtension
示例配置
这是一个示例配置,它在这里是为了解释事物,并且故意不完整。您还可以查看我网站使用的配置。
contentSecurityPolicy: snippets: slideshare: child-src: - https://www.slideshare.net policies: *.*: default-src: "'none'" form-action: "'none'" report-uri: https://report-uri.com.example.net report-to: default www.*.*: default-src: "'none'" script-src: - "'strict-dynamic'" - "'nonce'" - "'self'" - "'report-sample'" upgrade-insecure-requests: www.trainings.training: @extends: www.*.* connect-src: https://api.example.com admin.*.*: @extends: www.*.* admin.blog.add: @extends: admin.*.* connect-src: "'self'" admin.blog.edit: @extends: admin.blog.add policiesReportOnly: *.*: default-src: "'self'"
让我们解释
-
snippets
这里定义您的片段。一个片段由一个或多个内容安全策略指令组成,可以像这样通过addSnippet(string $snippetName)
方法添加到当前的内容安全策略头部:$this->contentSecurityPolicy->addSnippet($type);
您可以使用它来在页面上有视频时扩展策略。在 snippets.neon 中有示例片段,如果您想的话,可以直接将其包含在配置中。 -
policies
您的内容安全策略在这里。下面的键意味着[module.]presenter.action
,支持通配符。*.*
表示 对所有演示者和动作使用这些。如上例所示,我使用了相当严格的政策,稍后会允许更多。www.*.*
适用于 "www" 模块中的所有演示者和动作。@extends: www.*.*
此配置扩展www.*.*
配置,指定的任何值都将添加或合并。您可以使用它来扩展某些页面或动作的默认策略。您可以通过在指令名称前加!
来禁用合并,从而有效地覆盖扩展的值,请见下文。
-
policiesReportOnly
如policies
但旨在与Content-Security-Policy-Report-Only
头部一起使用,请见下文。
策略可以包含一些特殊的键和值
- 没有值的键,如上例中的
upgrade-insecure-requests:
,将使策略头部仅包含键名称而没有值 'nonce'
将向头部添加一个 CSP nonce ('nonce-somethingrandomandunique'
)。Nonces 在 CSP2 中定义,并在建议的策略中使用 CSP3'strict-dynamic'
。为此需要 spaze/nonce-generator。它还将返回不可变的 nonce,以便您可以将其添加到您的<script>
标签中。这可以通过 spaze/sri-macros 自动完成。
覆盖值
如果您不想将扩展值与原始值合并,请在配置中的指令名称前加上感叹号(!
)。以下是一个简单的示例配置
contentSecurityPolicy: policies: *.*: default-src: "'none'" www.*: @extends: *.* default-src: "'self'"
调用 getHeader('www:...')
将返回 default-src 'none' 'self'
,这没有意义,而且 'none'
甚至会被忽略。
将配置更改为如下(注意 default-src
中的 !
前缀)
contentSecurityPolicy: policies: *.*: default-src: "'none'" www.*: @extends: *.* !default-src: "'self'"
然后调用 getHeader('www:...')
将返回 default-src 'self'
,这可能是您想要的。
如何在 Nette 框架中发送生成的头部信息
$header = $this->contentSecurityPolicy->getHeader($presenter->getAction(true)); if ($header) { $this->httpResponse->setHeader('Content-Security-Policy', $header); }
例如,您可以通过以下方式从 \Nette\Application\Application
获取 $presenter
/** @var \Nette\Application\UI\Presenter $presenter */ $presenter = $this->application->getPresenter(); $actionName = $presenter->getAction(true);
并从依赖注入容器中获取 $this->application
public function __construct(private \Nette\Application\Application $application) { }
如果您在一个演示者(presenter)中,可以使用 $this->getAction(true)
代替。
仅报告策略
使用 policiesReportOnly
配置键来定义与 Content-Security-Policy-Report-Only
头部一起使用的策略
contentSecurityPolicy: policies: *.*: default-src: "'none'" policiesReportOnly: *.*: default-src: "'self'"
通过调用 getHeaderReportOnly()
方法获取策略
$header = $this->contentSecurityPolicy->getHeaderReportOnly($presenter->getAction(true)); if ($header) { $this->httpResponse->setHeader('Content-Security-Policy-Report-Only', $header); }
您可以发送 强制执行 和 仅报告 策略,这在策略升级等情况下非常有用
$header = $this->contentSecurityPolicy->getHeader($presenter->getAction(true)); if ($header) { $this->httpResponse->setHeader('Content-Security-Policy', $header); } $header = $this->contentSecurityPolicy->getHeaderReportOnly($presenter->getAction(true)); if ($header) { $this->httpResponse->setHeader('Content-Security-Policy-Report-Only', $header); }