我需要为yii2日志记录创建路径。此路径应避免记录密码等变量。根据文档(yii \ log \ Target)排除变量,我需要配置logVars。
在配置中:
'targets' => [
[
'class' => yii\log\FileTarget::className(),
'levels' => ['error', 'warning'],
'maxLogFiles' => 1000,
'maxFileSize' => 102400,
'logVars' => '!_POST[LoginForm[password]]',
],
但是LoginForm密码仍然出现在日志文件中。如何正确配置logVars。
P.S。我试过了!LoginForm.password,!_ POST.LoginForm.password
答案 0 :(得分:4)
我为同样的目的准备了代码 - 也许你会发现它很有用。
覆盖所选目标类中的ELF
,如:
getContextMessage()
使用<?php
namespace your\namespace\here;
use yii\helpers\ArrayHelper;
class FileTarget extends \yii\log\FileTarget
{
protected function getContextMessage()
{
$context = ArrayHelper::filter($GLOBALS, $this->logVars);
$result = [];
foreach ($context as $key => $value) {
if (\is_string($value) && stripos($key, 'password') !== false) {
$result[] = "\${$key} = '** PASSWORD HIDDEN **'";
} else {
$result[] = "\${$key} = " . \your\namespace\here\LogVarDumper::dumpAsString($value);
}
}
return implode("\n\n", $result);
}
}
覆盖VarDumper
课程(上面使用):
LogVarDumper
在日志配置中使用<?php
namespace your\namespace\here;
use yii\base\InvalidValueException;
/**
* Class LogVarDumper
* Extended to handle logs password fields darkening.
*/
class LogVarDumper extends \yii\helpers\VarDumper
{
private static $_objects;
private static $_output;
private static $_depth;
public static function dumpAsString($var, $depth = 10, $highlight = false)
{
self::$_output = '';
self::$_objects = [];
self::$_depth = $depth;
self::dumpInternal($var, 0);
if ($highlight) {
$result = highlight_string("<?php\n" . self::$_output, true);
self::$_output = preg_replace('/<\\?php<br \\/>/', '', $result, 1);
}
return self::$_output;
}
/**
* @param mixed $var variable to be dumped
* @param int $level depth level
* @param bool $passwordKey whether password related key was present in previous iteration
*/
private static function dumpInternal($var, $level, $passwordKey = false)
{
switch (gettype($var)) {
case 'boolean':
self::$_output .= $var ? 'true' : 'false';
break;
case 'integer':
self::$_output .= "$var";
break;
case 'double':
self::$_output .= "$var";
break;
case 'string':
if ($passwordKey) {
self::$_output .= "'** PASSWORD HIDDEN **'";
} else {
self::$_output .= "'" . addslashes($var) . "'";
}
break;
case 'resource':
self::$_output .= '{resource}';
break;
case 'NULL':
self::$_output .= 'null';
break;
case 'unknown type':
self::$_output .= '{unknown}';
break;
case 'array':
if (self::$_depth <= $level) {
self::$_output .= '[...]';
} elseif (empty($var)) {
self::$_output .= '[]';
} else {
$keys = array_keys($var);
$spaces = str_repeat(' ', $level * 4);
self::$_output .= '[';
foreach ($keys as $key) {
self::$_output .= "\n" . $spaces . ' ';
self::dumpInternal($key, 0);
self::$_output .= ' => ';
self::dumpInternal($var[$key], $level + 1, strpos(strtolower($key), 'password') !== false);
}
self::$_output .= "\n" . $spaces . ']';
}
break;
case 'object':
if (($id = array_search($var, self::$_objects, true)) !== false) {
self::$_output .= get_class($var) . '#' . ($id + 1) . '(...)';
} elseif (self::$_depth <= $level) {
self::$_output .= get_class($var) . '(...)';
} else {
$id = array_push(self::$_objects, $var);
$className = get_class($var);
$spaces = str_repeat(' ', $level * 4);
self::$_output .= "$className#$id\n" . $spaces . '(';
if ('__PHP_Incomplete_Class' !== get_class($var) && method_exists($var, '__debugInfo')) {
$dumpValues = $var->__debugInfo();
if (!is_array($dumpValues)) {
throw new InvalidValueException('__debuginfo() must return an array');
}
} else {
$dumpValues = (array) $var;
}
foreach ($dumpValues as $key => $value) {
$keyDisplay = strtr(trim($key), "\0", ':');
self::$_output .= "\n" . $spaces . " [$keyDisplay] => ";
self::dumpInternal($value, $level + 1);
}
self::$_output .= "\n" . $spaces . ')';
}
break;
}
}
}
。您可以使用所选目标的所有可用属性,现在名称中包含your\namespace\here\FileTarget
且字段值为字符串的所有字段都将记录password
而不是实际密码。
答案 1 :(得分:0)
默认目标组件仅过滤一级深度的键。
因此,您可以!_POST.LoginForm
过滤LoginForm的所有字段,但不过滤特定字段。
'logVars' = [
'_GET',
'_POST',
'_FILES',
'_COOKIE',
'_SESSION',
'_SERVER',
'!_POST.LoginForm'
],
除了在LoginForm中发布的任何字段外,它将为您提供所有默认日志记录。