最近yii2开发组成员Alexander Makarov写了一篇blog,关于youtube网站报错信息页面的分析。
当我们的程序在生产阶段的时候,不能将程序的信息暴露出来,这会给黑客破解网站的机会。youtube网站则使用了一种算法对报错信息进行加密,这样开发人员就能通过解密程序及时获得程序到底出了什么问题?
blog链接:https://en.rmcreative.ru/blog/youtubes-500-error-page/
而Alexander Makarov也说到在yii2中通过使用errorHander和encryptByKey方法能实现同样的目的,今天就将yii2对此实现写一篇教程,希望对你有用。
当然,我的新版网站也使用了此方法 可以通过 https://nai8.me/forum/detail.html?id=abc 看到效果。
errorHandler要实现上面目的需要对web.php的errorHandler进行配置,我们设置了自己的error报错视图,代码如下
'errorHandler' => [
'errorAction' => 'site/error',
],
这个配置在components中,yii2默认即配置如此,所以一般你不需要更改。
视图因为上面指定了errorAction = site/error,因此对应的视图就是site/view.php,这就是我们将来要编写错误显示的页面。
All Error我们知道针对于每个url,yii2框架会将其解析到对应控制器的action上,因此我们需要对每个控制器设置其error动作,在这里有一个小方法,你可以抽象出一个父类让所有的控制器继承它,然后在父类中进行error动作的指定即可。
代码如下
public function actions() {
return [
'error' => [
'class' => 'yii\web\ErrorAction',
'layout' => 'empty'
],
];
}
是的,我们重写了控制器的actions方法,含义是当出现error动作的时候由yii2的 yii\web\ErrorAction 接管,也就是说我们site/error.php视图是由yii\web\ErrorAction进行操作和传值的。
为了显示方法我们还通过 'layout' => 'empty' 设置了site/error.php视图自己的布局,如果不设置则使用yii2默认的。
传值现在我们知道对于每个控制器的动作,发生问题的时候都会由 yii\web\ErrorAction 并将结果渲染到site/error.php视图内,用户看到结果。
现在我们看看 yii\web\ErrorAction 都为 site/error.php视图 传递了什么?
// /vendor/yiisoft/yii2/web/ErrorAction.php
protected function getViewRenderParams()
{
return [
'name' => $this->getExceptionName(),
'message' => $this->getExceptionMessage(),
'exception' => $this->exception,
];
}
在这里我们看到可以使用 name / message / exception三个变量,它们的含义如下
- name 报错名字(比如404等)
- message 简单信息,一般会显示服务器错误等简短信息
- exception 错误对象,此错误的所有数据。
因此我在视图内进行了如下编码
<div class="site-error">
<h1>报错啦~</h1>
<div class="message">
<?= nl2br(Html::encode($message)) ?>
</div>
<div class="detail">
<strong>报错信息:</strong>
<?= $exception->getMessage();?>
</div>
</div>
但是这样会有问题,$exception->getMessage() 将错误的关键信息显示出来,对我们开发者是有用的,但是用户也看到了。
因此我们要对其进行加密,在这里使用 Alexander Makarov 说的encryptByKey方法,此方法需要一个key,然后对数据进行加密,对于加密后的结果我们可以使用 decryptByKey 进行解密。
encryptByKey好了,那就开始加密吧,yii2内置已经提供了,简单使用一下。
<?= Yii::$app->security->encryptByKey($exception->getMessage(),'abc');?>
ok,这样你就能看到下面截图的结果,这样我们在生产环境中也能及时获得某个页面为何出错了~