bicf / yii2-security-headers
安全导向的头信息管理
Requires
- yiisoft/yii2: 2.0.*
README
简介
Yii2实现CSP - 内容安全策略
另请参阅MDN文档
安装
建议通过运行以下命令通过composer进行安装
composer require bicf/yii2-security-headers "*"
或者,您可以手动将以下内容添加到您的composer.json中的require部分
{
"bicf/yii2-security-headers": "*"
}
之后运行composer update。
然后进行配置。
配置
版本1.1是模块实现。
在main.php中的securityHeader模块示例配置
[
'bootstrap'=>[
'securityHeader',
],
'modules' => [
'securityHeader' => [
'class' => bicf\securityheaders\Module::class,
'modules' => [
'XContentTypeOptions'=>[
'class' => 'bicf\securityheaders\modules\HeaderXContentTypeOptions',
'value' => 'nosniff',
],
'XFrameOptions'=>[
'class' => 'bicf\securityheaders\modules\HeaderXFrameOptions',
'value' => 'SAMEORIGIN',
],
'AccessControlAllowMethods'=>[
'class' => 'bicf\securityheaders\modules\HeaderAccessControlAllowMethods',
'value' => 'GET',
],
'AccessControlAllowOrigin'=>[
'class' => 'bicf\securityheaders\modules\HeaderAccessControlAllowOrigin',
'value' => 'https://api.example.com',
],
'ContentSecurityPolicyAcl'=>[
'class' => 'bicf\securityheaders\modules\HeaderContentSecurityPolicyAcl',
'enabled' => false,
'policies' => [
'default-src' => "'self'",
'frame-src' => "'self' www.facebook.com www.youtube.com www.google.com",
'img-src' => "'self' www.google-analytics.com",
'font-src' => "'self' fonts.gstatic.com maxcdn.bootstrapcdn.com",
'media-src' => "'self'",
'script-src' => "'self' www.google-analytics.com",
'style-src' => "'self' maxcdn.bootstrapcdn.com",
'connect-src' => "'self'",
'report-uri' => "/report-csp-acl",
],
],
'ContentSecurityPolicyMonitor'=>[
'class' => 'bicf\securityheaders\modules\HeaderContentSecurityPolicyMonitor',
'policies' => [
'default-src' => "'self'",
'frame-src' => "'self' www.facebook.com www.youtube.com www.google.com",
'img-src' => "'self' www.google-analytics.com",
'font-src' => "'self' fonts.gstatic.com maxcdn.bootstrapcdn.com",
'media-src' => "'self'",
'script-src' => "'self' www.google-analytics.com",
'style-src' => "'self' maxcdn.bootstrapcdn.com",
'connect-src' => "'self'",
'report-uri' => "/report-csp-acl",
],
],
],
],
],
'components' => [
// components stuff
// no need to add anything
],
]
内容安全策略头信息的Yii2集成
可能的集成方式
CSP可以通过签名或通过nonce令牌进行工作,请参阅
通过签名集成
只需简单地将签名添加到CSP配置中即可完成
示例
'style-src' => "'sha256-aqNNdDLnnrDOnTNdkJpYlAxKVJtLt9CtFLklmInuUAE=' 'sha256-6fwFCXmgb6H4XQGajtDSVG3YuKmX3dT1NkX4+z510Og=' 'sha256-ZdHxw9eWtnxUb3mk6tBS+gIiVUPE3pGM470keHPDFlE='",
这种集成不需要对框架代码进行修补,但即使签名数量很少,也会占用空间并难以维护。
通过nonce令牌集成
这种集成需要在框架(\yii\helpers\BaseHtml)级别进行一些(小的)修补,以充分利用nonce令牌。一旦集成,默认启用的nonce功能就不需要维护,并且对头的占用空间更小
以下是支持nonce参数的透明方式修补BaseHtml函数的版本。
对Html::script辅助函数的修补
修补后的\yii\helpers\BaseHtml::script()
public static function script($content, $options = []) { if(Yii::$app->response instanceof SecureRequestInterface){ $behavior = Yii::$app->response->getBehavior(SecureRequestInterface::CSP_NONCE_BEHAVIOR); if($behavior != null){ $options = array_merge(Yii::$app->response->getContentSecurityPolicyTokenArray(),$options ); } } return static::tag('script', $content, $options); }
项目资产所需的script标签
修补后的\yii\helpers\BaseHtml::jsFile()
public static function jsFile($url, $options = []) { $options['src'] = Url::to($url); if (isset($options['condition'])) { $condition = $options['condition']; unset($options['condition']); return self::wrapIntoCondition(static::tag('script', '', $options), $condition); } if(Yii::$app->response instanceof SecureRequestInterface){ $behavior = Yii::$app->response->getBehavior('cspBehavior'); if($behavior != null){ $options = array_merge(Yii::$app->response->getContentSecurityPolicyTokenArray(),$options ); } } return static::tag('script', '', $options); }
或者(更好)在jsFile函数内部调用script函数
public static function jsFile($url, $options = []) { $options['src'] = Url::to($url); if (isset($options['condition'])) { $condition = $options['condition']; unset($options['condition']); return self::wrapIntoCondition(static::tag('script', '', $options), $condition); } return static::script('', $options); }
对视图中的<script>的不同处理方法
在视图中添加script标签
当在视图或控制器中显式使用<script>时,解决方案是直接通过以下方式在标签中添加nonce参数
Yii::$app->response->getContentSecurityPolicyTokenAttribute()
在视图内部
<script <?= Yii::$app->response->getContentSecurityPolicyTokenAttribute();?> > alert("test"); </script>
修补过的 \yii\debug\Module::renderToolbar 函数
/** * Renders mini-toolbar at the end of page body. * * @param \yii\base\Event $event */ public function renderToolbar($event) { if (!$this->checkAccess() || Yii::$app->getRequest()->getIsAjax()) { return; } /* @var $view View */ $view = $event->sender; echo $view->renderDynamic('return Yii::$app->getModule("' . $this->id . '")->getToolbarHtml();'); // echo is used in order to support cases where asset manager is not available echo '<style>' . $view->renderPhpFile(__DIR__ . '/assets/toolbar.css') . '</style>'; echo '<script '.Yii::$app->response->getContentSecurityPolicyTokenAttribute().'>' . $view->renderPhpFile(__DIR__ . '/assets/toolbar.js') . '</script>'; }
具体来说,这一行
echo '<script '.Yii::$app->response->getContentSecurityPolicyTokenAttribute().'>' . $view->renderPhpFile(__DIR__ . '/assets/toolbar.js') . '</script>';
运行时禁用
由于在调用render之前不会发送任何头信息,因此可以根据需要禁用一个或多个模块。
public function actionIndex() { Yii::$app->getResponse()->modules['sample-module']->enabled=false; return $this->render("index"); }
旧版实现
这是旧版实现,通过扩展Request类来实现。
重要:如果您不设置配置,则不会发送任何头信息。
配置示例
[
'components' => [
'response' => [
'class' => 'bicf\securityheaders\components\Response',
'on afterPrepare' => ['bicf\securityheaders\components\Response','addSecurityHeaders'],
'modules' => [
'XContentTypeOptions'=>[
'class' => 'bicf\securityheaders\modules\HeaderXContentTypeOptions',
'value' => 'nosniff',
],
'AccessControlAllowMethods'=>[
'class' => 'bicf\securityheaders\modules\HeaderAccessControlAllowMethods2',
'value' => 'GET',
],
'AccessControlAllowOrigin'=>[
'class' => 'bicf\securityheaders\modules\HeaderAccessControlAllowOrigin',
'value' => 'https://api.example.com',
],
'ContentSecurityPolicyAcl'=>[
'class' => 'bicf\securityheaders\modules\HeaderContentSecurityPolicyAcl',
'enabled' => false,
'policies' => [
'default-src' => "'self'",
'frame-src' => "'self' www.facebook.com www.youtube.com www.google.com",
'img-src' => "'self' www.google-analytics.com",
'font-src' => "'self' fonts.gstatic.com maxcdn.bootstrapcdn.com",
'media-src' => "'self'",
'script-src' => "'self' www.google-analytics.com",
'style-src' => "'self' maxcdn.bootstrapcdn.com",
'connect-src' => "'self'",
'report-uri' => "/report-csp-acl",
],
],
'ContentSecurityPolicyMonitor'=>[
'class' => 'bicf\securityheaders\modules\HeaderContentSecurityPolicyMonitor',
'policies' => [
'default-src' => "'self'",
'frame-src' => "'self' www.facebook.com www.youtube.com www.google.com",
'img-src' => "'self' www.google-analytics.com",
'font-src' => "'self' fonts.gstatic.com maxcdn.bootstrapcdn.com",
'media-src' => "'self'",
'script-src' => "'self' www.google-analytics.com",
'style-src' => "'self' maxcdn.bootstrapcdn.com",
'connect-src' => "'self'",
'report-uri' => "/report-csp-acl",
],
],
],
],
],
]