isForbidden.php 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. <?php
  2. namespace App\Http\Middleware;
  3. use Agent;
  4. use App\Components\IPIP;
  5. use App\Components\QQWry;
  6. use Closure;
  7. use Illuminate\Http\Request;
  8. use Log;
  9. use Response;
  10. class isForbidden
  11. {
  12. /**
  13. * 限制机器人、指定IP访问
  14. *
  15. * @param Request $request
  16. * @param Closure $next
  17. *
  18. * @return mixed
  19. */
  20. public function handle(Request $request, Closure $next)
  21. {
  22. // 拒绝机器人访问
  23. if (sysConfig('is_forbid_robot') && Agent::isRobot()) {
  24. Log::info("识别到机器人访问(" . getClientIp() . ")");
  25. return Response::view(
  26. 'auth.error',
  27. ['message' => trans('error.ForbiddenRobot')],
  28. 403
  29. );
  30. }
  31. // 拒绝通过订阅链接域名访问网站,防止网站被探测
  32. if (false !== strpos(sysConfig('subscribe_domain'), $request->getHost())
  33. && ! str_contains(
  34. sysConfig('subscribe_domain'),
  35. sysConfig('website_url')
  36. )) {
  37. Log::info("识别到通过订阅链接访问,强制跳转至百度(" . getClientIp() . ")");
  38. return redirect('https://www.baidu.com');
  39. }
  40. $ip = getClientIP();
  41. if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
  42. Log::info('识别到IPv6,尝试解析:' . $ip);
  43. $isIPv6 = true;
  44. $ipInfo = getIPInfo($ip);
  45. } else {
  46. $isIPv6 = false;
  47. $ipInfo = QQWry::ip($ip); // 通过纯真IP库解析IPv4信息
  48. if (isset($ipInfo['error'])) {
  49. Log::info('无法识别IPv4,尝试使用IPIP的IP库解析:' . $ip);
  50. $ipip = IPIP::ip($ip);
  51. $ipInfo = [
  52. 'country' => $ipip['country_name'],
  53. 'province' => $ipip['region_name'],
  54. 'city' => $ipip['city_name'],
  55. ];
  56. } else {
  57. // 判断纯真IP库获取的国家信息是否与IPIP的IP库获取的信息一致,不一致则用IPIP的(因为纯真IP库的非大陆IP准确率较低)
  58. $ipip = IPIP::ip($ip);
  59. if ($ipInfo['country'] != $ipip['country_name']) {
  60. $ipInfo['country'] = $ipip['country_name'];
  61. $ipInfo['province'] = $ipip['region_name'];
  62. $ipInfo['city'] = $ipip['city_name'];
  63. }
  64. }
  65. }
  66. // 拒绝无IP请求
  67. if (empty($ipInfo) || empty($ipInfo['country'])) {
  68. return Response::view(
  69. 'auth.error',
  70. ['message' => trans('error.ForbiddenAccess')],
  71. 403
  72. );
  73. }
  74. if ( ! in_array($ipInfo['country'], ['本机地址', '局域网'])) {
  75. // 拒绝大陆IP访问
  76. if (sysConfig('is_forbid_china')) {
  77. if (($isIPv6 && $ipInfo['country'] === 'China')
  78. || ($ipInfo['country'] === '中国'
  79. && ! in_array(
  80. $ipInfo['province'],
  81. ['香港', '澳门', '台湾']
  82. ))) {
  83. Log::info('识别到大陆IP,拒绝访问:' . $ip);
  84. return Response::view(
  85. 'auth.error',
  86. [
  87. 'message' => trans(
  88. 'error.ForbiddenChina'
  89. ),
  90. ],
  91. 403
  92. );
  93. }
  94. }
  95. // 拒绝非大陆IP访问
  96. if (sysConfig('is_forbid_oversea')) {
  97. if (($isIPv6 && $ipInfo['country'] !== 'China') || $ipInfo['country'] !== '中国'
  98. || in_array($ipInfo['province'], ['香港', '澳门', '台湾'])) {
  99. Log::info(
  100. '识别到海外IP,拒绝访问:' . $ip . ' - ' . $ipInfo['country']
  101. );
  102. return Response::view(
  103. 'auth.error',
  104. [
  105. 'message' => trans(
  106. 'error.ForbiddenOversea'
  107. ),
  108. ],
  109. 403
  110. );
  111. }
  112. }
  113. }
  114. return $next($request);
  115. }
  116. }