AdminLog.php 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. <?php
  2. namespace app\admin\model;
  3. use Throwable;
  4. use think\Model;
  5. use app\admin\library\Auth;
  6. use think\model\relation\BelongsTo;
  7. /**
  8. * AdminLog模型
  9. */
  10. class AdminLog extends Model
  11. {
  12. protected $autoWriteTimestamp = true;
  13. protected $updateTime = false;
  14. /**
  15. * 自定义日志标题
  16. * @var string
  17. */
  18. protected string $title = '';
  19. /**
  20. * 自定义日志内容
  21. * @var string|array
  22. */
  23. protected string|array $data = '';
  24. /**
  25. * 忽略的链接正则列表
  26. * @var array
  27. */
  28. protected array $urlIgnoreRegex = [
  29. '/^(.*)\/(select|index|logout)$/i',
  30. ];
  31. protected array $desensitizationRegex = [
  32. '/(password|salt|token)/i'
  33. ];
  34. public static function instance()
  35. {
  36. $request = request();
  37. if (!isset($request->adminLog)) {
  38. $request->adminLog = new static();
  39. }
  40. return $request->adminLog;
  41. }
  42. /**
  43. * 设置标题
  44. * @param string $title
  45. */
  46. public function setTitle(string $title): void
  47. {
  48. $this->title = $title;
  49. }
  50. /**
  51. * 设置日志内容
  52. * @param string|array $data
  53. */
  54. public function setData(string|array $data): void
  55. {
  56. $this->data = $data;
  57. }
  58. /**
  59. * 设置忽略的链接正则列表
  60. * @param array|string $regex
  61. */
  62. public function setUrlIgnoreRegex(array|string $regex = []): void
  63. {
  64. $regex = is_array($regex) ? $regex : [$regex];
  65. $this->urlIgnoreRegex = array_merge($this->urlIgnoreRegex, $regex);
  66. }
  67. /**
  68. * 设置需要进行数据脱敏的正则列表
  69. * @param array|string $regex
  70. */
  71. public function setDesensitizationRegex(array|string $regex = []): void
  72. {
  73. $regex = is_array($regex) ? $regex : [$regex];
  74. $this->desensitizationRegex = array_merge($this->desensitizationRegex, $regex);
  75. }
  76. /**
  77. * 数据脱敏(只数组,根据数组 key 脱敏)
  78. * @param array|string $data
  79. * @return array|string
  80. */
  81. protected function desensitization(array|string $data): array|string
  82. {
  83. if (!is_array($data) || !$this->desensitizationRegex) {
  84. return $data;
  85. }
  86. foreach ($data as $index => &$item) {
  87. foreach ($this->desensitizationRegex as $reg) {
  88. if (preg_match($reg, $index)) {
  89. $item = "***";
  90. } elseif (is_array($item)) {
  91. $item = $this->desensitization($item);
  92. }
  93. }
  94. }
  95. return $data;
  96. }
  97. /**
  98. * 写入日志
  99. * @param string $title
  100. * @param string|array|null $data
  101. * @throws Throwable
  102. */
  103. public function record(string $title = '', string|array $data = null): void
  104. {
  105. $auth = Auth::instance();
  106. $adminId = $auth->isLogin() ? $auth->id : 0;
  107. $username = $auth->isLogin() ? $auth->username : request()->param('username', __('Unknown'));
  108. $controller = str_replace('.', '/', request()->controller(true));
  109. $action = request()->action(true);
  110. $path = $controller . '/' . $action;
  111. if ($this->urlIgnoreRegex) {
  112. foreach ($this->urlIgnoreRegex as $item) {
  113. if (preg_match($item, $path)) {
  114. return;
  115. }
  116. }
  117. }
  118. $data = $data ?: $this->data;
  119. if (!$data) {
  120. $data = request()->param('', null, 'trim,strip_tags,htmlspecialchars');
  121. }
  122. $data = $this->desensitization($data);
  123. $title = $title ?: $this->title;
  124. if (!$title) {
  125. $controllerTitle = AdminRule::where('name', $controller)->value('title');
  126. $title = AdminRule::where('name', $path)->value('title');
  127. $title = $title ?:'(' . $action . ')';
  128. $title = $controllerTitle ? ($controllerTitle . '-' . $title) : $title;
  129. }
  130. self::create([
  131. 'ADMIN_ID' => $adminId,
  132. 'USERNAME' => $username,
  133. 'URL' => substr(request()->url(), 0, 1500),
  134. 'TITLE' => $title,
  135. 'DATA' => !is_scalar($data) ? json_encode($data) : $data,
  136. 'IP' => request()->ip(),
  137. 'USERAGENT' => substr(request()->server('HTTP_USER_AGENT'), 0, 255),
  138. ]);
  139. }
  140. public function admin(): BelongsTo
  141. {
  142. return $this->belongsTo(Admin::class);
  143. }
  144. }