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", ], ], ], ], ], ]