portal.mkgtu.ru/common/components/SecureHeaders/ContentSecurityPolicy.php

124 lines
3.3 KiB
PHP
Executable File

<?php
namespace common\components\SecureHeaders;
use hyperia\security\headers\PolicyInterface;
class ContentSecurityPolicy implements PolicyInterface
{
private $directives;
private $reportUri;
private $requireSriForScript;
private $requireSriForStyle;
private $blockAllMixedContent;
private $upgradeInsecureRequests;
private $defaultDirectives = [
'connect-src' => "'self'",
'font-src' => "'self'",
'frame-src' => "'self'",
'img-src' => "'self' data:",
'manifest-src' => "'self'",
'object-src' => "'self'",
'prefetch-src' => "'self'",
'script-src' => "'self' 'unsafe-inline'",
'style-src' => "'self' 'unsafe-inline'",
'media-src' => "'self'",
'form-action' => "'self'",
'worker-src' => "'self'",
];
private $defaultCsp = [
'default-src' => "*"
];
public function __construct(array $directives, array $params, string $reportUri)
{
$this->directives = $directives;
$this->reportUri = $reportUri;
$this->requireSriForScript = $params['requireSriForScript'] ?? false;
$this->requireSriForStyle = $params['requireSriForStyle'] ?? false;
$this->blockAllMixedContent = $params['blockAllMixedContent'] ?? false;
$this->upgradeInsecureRequests = $params['upgradeInsecureRequests'] ?? false;
}
public function getName(): string
{
return 'Content-Security-Policy';
}
public function getValue(): string
{
$result = '';
$cspDirectives = $this->buildPolicyArray();
foreach ($cspDirectives as $directive => $value) {
$result .= $directive . ' ' . $value . '; ';
}
if ($this->blockAllMixedContent) {
$result .= 'block-all-mixed-content; ';
}
if ($this->upgradeInsecureRequests) {
$result .= 'upgrade-insecure-requests; ';
}
return trim((string)$result, '; ');
}
public function isValid(): bool
{
$allowedDirectives = array_keys(array_merge($this->defaultCsp, $this->defaultDirectives));
foreach ($this->directives as $directive => $value) {
if (!in_array($directive, $allowedDirectives) && !empty($value)) {
return false;
}
}
return true;
}
private function getCspReportUri(): array
{
$report = [];
if (!empty($this->reportUri)) {
$report = [
'report-uri' => $this->reportUri . '/r/d/csp/enforce'
];
}
return $report;
}
private function getCspSubresourceIntegrity(): array
{
$result = [];
if ($this->requireSriForScript) {
$values[] = 'script';
}
if ($this->requireSriForStyle) {
$values[] = 'style';
}
if (!empty($values)) {
$result = [
'require-sri-for' => implode(' ', $values)
];
}
return $result;
}
private function buildPolicyArray(): array
{
return array_merge(
$this->defaultCsp,
$this->defaultDirectives,
$this->directives,
$this->getCspSubresourceIntegrity(),
$this->getCspReportUri()
);
}
}