Validator.php 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. <?php
  2. namespace BCJD;
  3. /**
  4. * Validator - 输入验证与净化
  5. *
  6. * 安全特性:
  7. * - HTML 转义(XSS 防护)
  8. * - URL 格式校验
  9. * - 字符串长度限制
  10. * - 白名单样式类校验
  11. */
  12. class Validator
  13. {
  14. /**
  15. * HTML 转义(XSS 防护)
  16. */
  17. public static function escape(string $value): string
  18. {
  19. return htmlspecialchars($value, ENT_QUOTES | ENT_HTML5, 'UTF-8', false);
  20. }
  21. /**
  22. * 净化 URL(仅允许 http/https 协议)
  23. */
  24. public static function sanitizeUrl(string $url): string
  25. {
  26. $url = trim($url);
  27. // 禁止 javascript: data: 等危险协议
  28. if (preg_match('/^(javascript|data|file|php):/i', $url)) {
  29. return '';
  30. }
  31. // 自动补全协议
  32. if (!preg_match('#^https?://#i', $url)) {
  33. $url = 'https://' . $url;
  34. }
  35. return filter_var($url, FILTER_VALIDATE_URL) !== false ? $url : '';
  36. }
  37. /**
  38. * SVG 净化:仅允许安全的 SVG 标签和属性
  39. */
  40. public static function sanitizeSvg(string $svg): string
  41. {
  42. // 只允许纯 SVG 标签(移除 script/style/foreignObject 等危险元素)
  43. $svg = strip_tags($svg, '<svg><path><circle><rect><line><polyline><polygon><ellipse><g><defs><use><text><tspan><stop><linearGradient><radialGradient><filter><feGaussianBlur><feOffset><feColorMatrix><feBlend><feMerge><feMergeNode>');
  44. // 移除 on* 事件属性(如 onclick, onload, onerror)
  45. $svg = preg_replace('/\bon\w+\s*=\s*(["\']).*?\1/is', '', $svg);
  46. // 移除 href 属性(防止通过 href="javascript:..." 执行脚本)
  47. $svg = preg_replace('/\bhref\s*=\s*(["\']).*?\1/i', '', $svg);
  48. // 移除 xlink:href(同上)
  49. $svg = preg_replace('/\bxlink:href\s*=\s*(["\']).*?\1/i', '', $svg);
  50. return $svg;
  51. }
  52. /**
  53. * 验证分组名(英文+数字+下划线)
  54. */
  55. public static function validateGroupName(string $name): string
  56. {
  57. $name = trim($name);
  58. if (!preg_match('/^[a-zA-Z0-9_\-]{1,50}$/', $name)) {
  59. return 'default';
  60. }
  61. return $name;
  62. }
  63. /**
  64. * 白名单校验标签样式类
  65. */
  66. public static function validateTagClass(string $class): string
  67. {
  68. $allowed = ['', 'ok', 'warn'];
  69. return in_array($class, $allowed, true) ? $class : '';
  70. }
  71. /**
  72. * 截断字符串到指定长度
  73. */
  74. public static function truncate(string $value, int $maxLength = 255): string
  75. {
  76. return mb_substr(trim($value), 0, $maxLength, 'UTF-8');
  77. }
  78. /**
  79. * 净化关键字(移除特殊字符)
  80. */
  81. public static function sanitizeKeywords(string $keywords): string
  82. {
  83. return preg_replace('/[^\p{L}\p{N}\s\-_]/u', '', trim($keywords));
  84. }
  85. /**
  86. * 验证密码强度
  87. */
  88. public static function validatePassword(string $password): ?string
  89. {
  90. if (strlen($password) < 6) {
  91. return '密码至少需要6个字符';
  92. }
  93. if (strlen($password) > 128) {
  94. return '密码长度不能超过128个字符';
  95. }
  96. return null;
  97. }
  98. /**
  99. * 安全地清理用户输入:去除不可见控制字符
  100. */
  101. public static function stripControlChars(string $value): string
  102. {
  103. return preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/', '', $value);
  104. }
  105. }