class ResponseCspSubscriber in Content-Security-Policy 8
Class ResponseSubscriber.
Hierarchy
- class \Drupal\csp\EventSubscriber\ResponseCspSubscriber implements \Symfony\Component\EventDispatcher\EventSubscriberInterface
Expanded class hierarchy of ResponseCspSubscriber
1 file declares its use of ResponseCspSubscriber
- ResponseCspSubscriberTest.php in tests/
src/ Unit/ EventSubscriber/ ResponseCspSubscriberTest.php
1 string reference to 'ResponseCspSubscriber'
1 service uses ResponseCspSubscriber
File
- src/
EventSubscriber/ ResponseCspSubscriber.php, line 21
Namespace
Drupal\csp\EventSubscriberView source
class ResponseCspSubscriber implements EventSubscriberInterface {
/**
* The Config Factory service.
*
* @var \Drupal\Core\Config\ConfigFactoryInterface
*/
protected $configFactory;
/**
* The Library Policy Builder service.
*
* @var \Drupal\csp\LibraryPolicyBuilder
*/
protected $libraryPolicyBuilder;
/**
* The Reporting Handler Plugin Manager service.
*
* @var \Drupal\csp\ReportingHandlerPluginManager
*/
private $reportingHandlerPluginManager;
/**
* The Event Dispatcher service.
*
* @var \Symfony\Component\EventDispatcher\EventDispatcherInterface
*/
private $eventDispatcher;
/**
* Constructs a new ResponseSubscriber object.
*
* @param \Drupal\Core\Config\ConfigFactoryInterface $configFactory
* Config Factory service.
* @param \Drupal\csp\LibraryPolicyBuilder $libraryPolicyBuilder
* The Library Parser service.
* @param \Drupal\csp\ReportingHandlerPluginManager $reportingHandlerPluginManager
* The Reporting Handler Plugin Manager service.
* @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $eventDispatcher
* The Event Dispatcher Service.
*/
public function __construct(ConfigFactoryInterface $configFactory, LibraryPolicyBuilder $libraryPolicyBuilder, ReportingHandlerPluginManager $reportingHandlerPluginManager, EventDispatcherInterface $eventDispatcher) {
$this->configFactory = $configFactory;
$this->libraryPolicyBuilder = $libraryPolicyBuilder;
$this->reportingHandlerPluginManager = $reportingHandlerPluginManager;
$this->eventDispatcher = $eventDispatcher;
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
$events[KernelEvents::RESPONSE] = [
'onKernelResponse',
];
return $events;
}
/**
* Add Content-Security-Policy header to response.
*
* @param \Symfony\Component\HttpKernel\Event\FilterResponseEvent $event
* The Response event.
*/
public function onKernelResponse(FilterResponseEvent $event) {
if (!$event
->isMasterRequest()) {
return;
}
$cspConfig = $this->configFactory
->get('csp.settings');
$libraryDirectives = $this->libraryPolicyBuilder
->getSources();
$response = $event
->getResponse();
if ($response instanceof CacheableResponseInterface) {
$response
->getCacheableMetadata()
->addCacheTags([
'config:csp.settings',
]);
}
foreach ([
'report-only',
'enforce',
] as $policyType) {
if (!$cspConfig
->get($policyType . '.enable')) {
continue;
}
$policy = new Csp();
$policy
->reportOnly($policyType == 'report-only');
foreach ($cspConfig
->get($policyType . '.directives') ?: [] as $directiveName => $directiveOptions) {
if (is_bool($directiveOptions)) {
$policy
->setDirective($directiveName, TRUE);
continue;
}
// This is a directive with a simple array of values.
if (!isset($directiveOptions['base'])) {
$policy
->setDirective($directiveName, $directiveOptions);
continue;
}
switch ($directiveOptions['base']) {
case 'self':
$policy
->setDirective($directiveName, [
Csp::POLICY_SELF,
]);
break;
case 'none':
$policy
->setDirective($directiveName, [
Csp::POLICY_NONE,
]);
break;
case 'any':
$policy
->setDirective($directiveName, [
Csp::POLICY_ANY,
]);
break;
default:
// Initialize to an empty value so that any alter subscribers can
// tell that this directive was enabled.
$policy
->setDirective($directiveName, []);
}
if (!empty($directiveOptions['flags'])) {
$policy
->appendDirective($directiveName, array_map(function ($value) {
return "'" . $value . "'";
}, $directiveOptions['flags']));
}
if (!empty($directiveOptions['sources'])) {
$policy
->appendDirective($directiveName, $directiveOptions['sources']);
}
if (isset($libraryDirectives[$directiveName])) {
$policy
->appendDirective($directiveName, $libraryDirectives[$directiveName]);
}
}
$reportingPluginId = $cspConfig
->get($policyType . '.reporting.plugin');
if ($reportingPluginId) {
$reportingOptions = $cspConfig
->get($policyType . '.reporting.options') ?: [];
$reportingOptions += [
'type' => $policyType,
];
try {
$this->reportingHandlerPluginManager
->createInstance($reportingPluginId, $reportingOptions)
->alterPolicy($policy);
} catch (PluginException $e) {
watchdog_exception('csp', $e);
}
}
$this->eventDispatcher
->dispatch(CspEvents::POLICY_ALTER, new PolicyAlterEvent($policy, $response));
if ($headerValue = $policy
->getHeaderValue()) {
$response->headers
->set($policy
->getHeaderName(), $headerValue);
}
}
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
ResponseCspSubscriber:: |
protected | property | The Config Factory service. | |
ResponseCspSubscriber:: |
private | property | The Event Dispatcher service. | |
ResponseCspSubscriber:: |
protected | property | The Library Policy Builder service. | |
ResponseCspSubscriber:: |
private | property | The Reporting Handler Plugin Manager service. | |
ResponseCspSubscriber:: |
public static | function | Returns an array of event names this subscriber wants to listen to. | |
ResponseCspSubscriber:: |
public | function | Add Content-Security-Policy header to response. | |
ResponseCspSubscriber:: |
public | function | Constructs a new ResponseSubscriber object. |