Explorar el Código

IP地址查询整合与增强

兔姬桑 hace 4 años
padre
commit
e6da11dede

+ 2 - 1
.env.example

@@ -48,4 +48,5 @@ MAIL_PASSWORD=password
 MAILGUN_DOMAIN=
 MAILGUN_SECRET=
 
-REDIRECT_HTTPS=true
+REDIRECT_HTTPS=true
+BAIDU_APP_AK =

+ 1 - 1
app/Components/Helpers.php

@@ -107,7 +107,7 @@ class Helpers
             'Y-m-d',
             strtotime("+" . $data . " days")
         );
-        $user->reg_ip          = getClientIp();
+        $user->reg_ip          = IP::getClientIp();
         $user->inviter_id      = $inviter_id;
         $user->reset_time      = null;
         $user->status          = 0;

+ 247 - 0
app/Components/IP.php

@@ -0,0 +1,247 @@
+<?php
+
+namespace App\Components;
+
+use Exception;
+use GeoIp2\Database\Reader;
+use GeoIp2\Exception\AddressNotFoundException;
+use GuzzleHttp\Client;
+use IP2Location\Database;
+use Ip2Region;
+use ipip\db\City;
+use Log;
+use MaxMind\Db\Reader\InvalidDatabaseException;
+
+class IP
+{
+
+    // 获取IP地址信息
+    public static function getIPInfo($ip)
+    {
+        // IPv6 推荐使用ip.sb
+        if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
+            Log::info('识别到IPv6,尝试解析:' . $ip);
+            $ipInfo = IP::IPSB($ip);
+        } else {
+            $ipInfo = IP::ip2Region($ip);
+            if ( ! $ipInfo) {
+                Log::info('无法识别,尝试使用【IPIP库】库解析:' . $ip);
+                $ipInfo = IP::ip2Location($ip);
+            }
+        }
+
+        return $ipInfo;
+    }
+
+    // 通过api.ip.sb查询IP地址的详细信息
+    public static function IPSB($ip)
+    {
+        $request = (new Client(['timeout' => 15]))
+            ->get('https://api.ip.sb/geoip/' . $ip);
+        $message = json_decode($request->getBody(), true);
+
+        if ($request->getStatusCode() == 200) {
+            return $message;
+        }
+
+        Log::error('解析IPv6异常:' . $ip . PHP_EOL . var_export($request, true));
+
+        return false;
+    }
+
+    // 通过ip2Region查询IP地址的详细信息 ← 聚合 淘宝IP库,GeoIP,纯真IP库
+    public static function ip2Region(string $ip)
+    {
+        $ipInfo = false;
+        try {
+            $ipInfo = (new Ip2Region())->memorySearch($ip);
+        } catch (Exception $e) {
+            Log::error('【淘宝IP库】错误信息:' . $e->getMessage());
+        }
+
+        if ($ipInfo) {
+            $location = explode("|", $ipInfo['region']);
+
+            return [
+                'country'  => $location[0] ?: '',
+                'province' => $location[2] ?: '',
+                'city'     => $location[3] ?: '',
+            ];
+        }
+
+        return $ipInfo;
+    }
+
+    //// 通过ip2Location查询IP地址的详细信息
+    public static function ip2Location(string $ip)
+    {
+        $filePath = database_path('IP2LOCATION-LITE-DB3.IPV6.BIN');
+        try {
+            $location = (new Database($filePath, Database::FILE_IO))
+                ->lookup(
+                    $ip,
+                    [
+                        Database::CITY_NAME,
+                        Database::REGION_NAME,
+                        Database::COUNTRY_NAME,
+                    ]
+                );
+
+            return [
+                'country'  => $location['countryName'],
+                'province' => $location['regionName'],
+                'city'     => $location['cityName'],
+            ];
+        } catch (Exception $e) {
+            Log::error('【ip2Location】错误信息:' . $e->getMessage());
+        }
+
+        return false;
+    }
+
+    // 通过IPIP查询IP地址的详细信息
+    public static function IPIP(string $ip): array
+    {
+        $filePath = database_path('ipip.ipdb');
+        $location = (new City($filePath))->findMap($ip, 'CN');
+
+        return [
+            'country'  => $location['country_name'],
+            'province' => $location['region_name'],
+            'city'     => $location['city_name'],
+        ];
+    }
+
+    // 通过ip.taobao.com查询IP地址的详细信息
+    public static function TaoBao(string $ip)
+    {
+        // 依据 http://ip.taobao.com/instructions 开发
+        $request = (new Client(['timeout' => 15]))
+            ->get(
+                'http://ip.taobao.com/outGetIpInfo?ip=' . $ip . '&accessKey=alibaba-inc'
+            );
+        $message = json_decode($request->getBody(), true);
+
+        if ($request->getStatusCode() == 200) {
+            if ($message['code'] === 0) {
+                return [
+                    'country'  => $message['data']['country'] === "XX" ? '' : $message['data']['country'],
+                    'province' => $message['data']['region'] === "XX" ? '' : $message['data']['region'],
+                    'city'     => $message['data']['city'] === "XX" ? '' : $message['data']['city'],
+                ];
+            }
+
+            Log::error(
+                '【淘宝IP库】返回错误信息:' . $ip . PHP_EOL . var_export(
+                    $message['msg'],
+                    true
+                )
+            );
+        } else {
+            Log::error(
+                '【淘宝IP库】解析异常:' . $ip . PHP_EOL . var_export($request, true)
+            );
+        }
+
+        return false;
+    }
+
+    // 通过api.map.baidu.com查询IP地址的详细信息
+    public static function Baidu(string $ip)
+    {
+        if ( ! env('BAIDU_APP_AK')) {
+            Log::error('【百度IP库】AK信息缺失');
+
+            return false;
+        }
+        // 依据 http://lbsyun.baidu.com/index.php?title=webapi/ip-api 开发
+        $request = (new Client(['timeout' => 15]))
+            ->get(
+                'https://api.map.baidu.com/location/ip?ak=' . env(
+                    'BAIDU_APP_AK'
+                ) . '&' . $ip . '&coor=bd09ll'
+            );
+        $message = json_decode($request->getBody(), true);
+
+        if ($request->getStatusCode() == 200) {
+            if ($message['status'] === 0) {
+                return [
+                    'country'  => $message['content']['address_detail']['country'],
+                    'province' => $message['content']['address_detail']['province'],
+                    'city'     => $message['content']['address_detail']['city'],
+                ];
+            }
+
+            Log::error(
+                '【百度IP库】返回错误信息:' . $ip . PHP_EOL . var_export(
+                    $message['message'],
+                    true
+                )
+            );
+        } else {
+            Log::error(
+                '【百度IP库】解析异常:' . $ip . PHP_EOL . var_export($request, true)
+            );
+        }
+
+        return false;
+    }
+
+    // 通过GeoIP2查询IP地址的详细信息
+    public static function GeoIP2(string $ip)
+    {
+        $filePath = database_path('maxmind.mmdb');
+        try {
+            $location = (new Reader($filePath))->city($ip);
+
+            return [
+                'country'  => $location->country->names['zh-CN'],
+                'province' => '',
+                'city'     => $location->city->name ?? '',
+            ];
+        } catch (AddressNotFoundException $e) {
+            Log::error('【GeoIP2】查询失败:' . $ip);
+        } catch (InvalidDatabaseException $e) {
+            Log::error('【GeoIP2】数据库无效:' . $ip);
+        }
+
+        return false;
+    }
+
+    // 获取访客真实IP
+    public static function getClientIP()
+    {
+        /*
+         * 访问时用localhost访问的,读出来的是“::1”是正常情况
+         * ::1说明开启了IPv6支持,这是IPv6下的本地回环地址的表示
+         * 使用IPv4地址访问或者关闭IPv6支持都可以不显示这个
+         */
+        if (isset($_SERVER)) {
+            if (isset($_SERVER['HTTP_CF_CONNECTING_IP'])) {
+                $_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_CF_CONNECTING_IP'];
+                $ip                     = $_SERVER['REMOTE_ADDR'];
+            } elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
+                $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
+            } elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {
+                $ip = $_SERVER['HTTP_CLIENT_IP'];
+            } elseif (isset($_SERVER['REMOTE_ADDR'])) {
+                $ip = $_SERVER['REMOTE_ADDR'];
+            } else {
+                $ip = 'unknown';
+            }
+        } elseif (getenv('HTTP_X_FORWARDED_FOR')) {
+            $ip = getenv('HTTP_X_FORWARDED_FOR');
+        } elseif (getenv('HTTP_CLIENT_IP')) {
+            $ip = getenv('HTTP_CLIENT_IP');
+        } else {
+            $ip = getenv('REMOTE_ADDR');
+        }
+
+        if (trim($ip) === '::1') {
+            $ip = '127.0.0.1';
+        }
+
+        return $ip;
+    }
+
+}

+ 0 - 24
app/Components/IPIP.php

@@ -1,24 +0,0 @@
-<?php
-
-namespace App\Components;
-
-use ipip\db\City;
-
-class IPIP
-{
-
-    /**
-     * 查询IP地址的详细信息
-     *
-     * @param  string  $ip  IPv4
-     *
-     * @return array|null
-     */
-    public static function ip($ip): ?array
-    {
-        $filePath = database_path('ipip.ipdb');
-
-        return (new City($filePath))->findMap($ip, 'CN');
-    }
-
-}

+ 0 - 24
app/Components/QQWry.php

@@ -1,24 +0,0 @@
-<?php
-
-namespace App\Components;
-
-use itbdw\Ip\IpLocation;
-
-class QQWry
-{
-
-    /**
-     * 查询IP地址的详细信息
-     *
-     * @param  string  $ip  IPv4
-     *
-     * @return array
-     */
-    public static function ip($ip): array
-    {
-        $filePath = database_path('qqwry.dat');
-
-        return IpLocation::getLocation($ip, $filePath);
-    }
-
-}

+ 4 - 1
app/Exceptions/Handler.php

@@ -2,6 +2,7 @@
 
 namespace App\Exceptions;
 
+use App\Components\IP;
 use ErrorException;
 use Illuminate\Auth\AuthenticationException;
 use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
@@ -74,7 +75,9 @@ class Handler extends ExceptionHandler
 
         // 捕获访问异常
         if ($exception instanceof NotFoundHttpException) {
-            Log::info("异常请求:" . $request->fullUrl() . ",IP:" . getClientIp());
+            Log::info(
+                "异常请求:" . $request->fullUrl() . ",IP:" . IP::getClientIp()
+            );
 
             if ($request->ajax()) {
                 return Response::json(

+ 2 - 1
app/Http/Controllers/Admin/ToolsController.php

@@ -3,6 +3,7 @@
 namespace App\Http\Controllers\Admin;
 
 use App\Components\Helpers;
+use App\Components\IP;
 use App\Http\Controllers\Controller;
 use App\Models\User;
 use DB;
@@ -197,7 +198,7 @@ class ToolsController extends Controller
                     $obj->protocol        = $user->protocol;
                     $obj->obfs            = $user->obfs;
                     $obj->expired_at      = '2099-01-01';
-                    $obj->reg_ip          = getClientIp();
+                    $obj->reg_ip          = IP::getClientIp();
                     $obj->created_at      = date('Y-m-d H:i:s');
                     $obj->updated_at      = date('Y-m-d H:i:s');
                     $obj->save();

+ 6 - 22
app/Http/Controllers/AdminController.php

@@ -3,9 +3,8 @@
 namespace App\Http\Controllers;
 
 use App\Components\Helpers;
-use App\Components\IPIP;
+use App\Components\IP;
 use App\Components\PushNotification;
-use App\Components\QQWry;
 use App\Models\Article;
 use App\Models\Config;
 use App\Models\Country;
@@ -328,7 +327,7 @@ class AdminController extends Controller
             );
             $user->level           = $request->input('level') ?: 0;
             $user->group_id        = $request->input('group_id') ?: 0;
-            $user->reg_ip          = getClientIp();
+            $user->reg_ip          = IP::getClientIp();
             $user->reset_time      = $request->input('reset_time') > date(
                 'Y-m-d'
             ) ? $request->input('reset_time') : null;
@@ -477,13 +476,7 @@ class AdminController extends Controller
                     'remark'          => str_replace(
                         "eval",
                         "",
-                        str_replace(
-                            "atob",
-                            "",
-                            $request->input(
-                                'remark'
-                            )
-                        )
+                        str_replace("atob", "", $request->input('remark'))
                     ),
                     'level'           => $request->input('level'),
                     'group_id'        => $request->input('group_id'),
@@ -498,7 +491,7 @@ class AdminController extends Controller
                 }
 
                 // 非演示环境才可以修改管理员密码
-                if ( ! empty($password) && ! (config('app.demo') && $id == 1)) {
+                if ( ! empty($password) && ! (env('APP_DEMO') && $id == 1)) {
                     $data['password'] = Hash::make($password);
                 }
 
@@ -1943,18 +1936,9 @@ class AdminController extends Controller
             if ($log->ip == null || strpos($log->ip, ',') !== false) {
                 continue;
             }
-            $ipInfo = QQWry::ip($log->ip);
-            if (isset($ipInfo['error'])) {
-                // 用IPIP的库再试一下
-                $ipip   = IPIP::ip($log->ip);
-                $ipInfo = [
-                    'country'  => $ipip['country_name'],
-                    'province' => $ipip['region_name'],
-                    'city'     => $ipip['city_name'],
-                ];
-            }
+            $ipInfo = IP::getIPInfo($log->ip);
 
-            $log->ipInfo = $ipInfo['country'] . ' ' . $ipInfo['province'] . ' ' . $ipInfo['city'];
+            $log->ipInfo = implode(' ', $ipInfo);
         }
 
         $view['list']     = $onlineIPLogs;

+ 14 - 40
app/Http/Controllers/AuthController.php

@@ -3,8 +3,7 @@
 namespace App\Http\Controllers;
 
 use App\Components\Helpers;
-use App\Components\IPIP;
-use App\Components\QQWry;
+use App\Components\IP;
 use App\Mail\activeUser;
 use App\Mail\resetPassword;
 use App\Mail\sendVerifyCode;
@@ -118,7 +117,7 @@ class AuthController extends Controller
             }
 
             // 写入登录日志
-            $this->addUserLoginLog($user->id, getClientIp());
+            $this->addUserLoginLog($user->id, IP::getClientIp());
 
             // 更新登录信息
             Auth::getUser()->update(['last_login' => time()]);
@@ -213,43 +212,21 @@ class AuthController extends Controller
      */
     private function addUserLoginLog(int $userId, string $ip): void
     {
-        if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
-            Log::info('识别到IPv6,尝试解析:' . $ip);
-            $ipInfo = getIPInfo($ip);
-        } else {
-            $ipInfo = QQWry::ip($ip); // 通过纯真IP库解析IPv4信息
-            if (isset($ipInfo['error'])) {
-                Log::info('无法识别IPv4,尝试使用IPIP的IP库解析:' . $ip);
-                $ipip   = IPIP::ip($ip);
-                $ipInfo = [
-                    'country'  => $ipip['country_name'],
-                    'province' => $ipip['region_name'],
-                    'city'     => $ipip['city_name'],
-                ];
-            } else {
-                // 判断纯真IP库获取的国家信息是否与IPIP的IP库获取的信息一致,不一致则用IPIP的(因为纯真IP库的非大陆IP准确率较低)
-                $ipip = IPIP::ip($ip);
-                if ($ipInfo['country'] != $ipip['country_name']) {
-                    $ipInfo['country']  = $ipip['country_name'];
-                    $ipInfo['province'] = $ipip['region_name'];
-                    $ipInfo['city']     = $ipip['city_name'];
-                }
-            }
-        }
+        $ipLocation = IP::getIPInfo($ip);
 
-        if (empty($ipInfo) || empty($ipInfo['country'])) {
+        if (empty($ipLocation) || empty($ipLocation['country'])) {
             Log::warning("获取IP信息异常:" . $ip);
         }
 
         $log           = new UserLoginLog();
         $log->user_id  = $userId;
         $log->ip       = $ip;
-        $log->country  = $ipInfo['country'] ?? '';
-        $log->province = $ipInfo['province'] ?? '';
-        $log->city     = $ipInfo['city'] ?? '';
-        $log->county   = $ipInfo['county'] ?? '';
-        $log->isp      = $ipInfo['isp'] ?? ($ipInfo['organization'] ?? '');
-        $log->area     = $ipInfo['area'] ?? '';
+        $log->country  = $ipLocation['country'] ?? '';
+        $log->province = $ipLocation['province'] ?? '';
+        $log->city     = $ipLocation['city'] ?? '';
+        $log->county   = $ipLocation['county'] ?? '';
+        $log->isp      = $ipLocation['isp'] ?? ($ipLocation['organization'] ?? '');
+        $log->area     = $ipLocation['area'] ?? '';
         $log->save();
     }
 
@@ -265,7 +242,7 @@ class AuthController extends Controller
     // 注册
     public function register(Request $request)
     {
-        $cacheKey = 'register_times_' . md5(getClientIp()); // 注册限制缓存key
+        $cacheKey = 'register_times_' . md5(IP::getClientIp()); // 注册限制缓存key
 
         if ($request->isMethod('POST')) {
             $validator = Validator::make(
@@ -959,6 +936,7 @@ class AuthController extends Controller
                 ]
             );
         }
+        $ip = IP::getClientIP();
 
         // 校验域名邮箱黑白名单
         if (sysConfig('is_email_filtering')) {
@@ -976,7 +954,7 @@ class AuthController extends Controller
         }
 
         // 防刷机制
-        if (Cache::has('send_verify_code_' . md5(getClientIP()))) {
+        if (Cache::has('send_verify_code_' . md5($ip))) {
             return Response::json(
                 ['status' => 'fail', 'message' => trans('auth.register_anti')]
             );
@@ -994,11 +972,7 @@ class AuthController extends Controller
 
         $this->addVerifyCode($email, $code);
 
-        Cache::put(
-            'send_verify_code_' . md5(getClientIP()),
-            getClientIP(),
-            Minute
-        );
+        Cache::put('send_verify_code_' . md5($ip), $ip, Minute);
 
         return Response::json(
             ['status' => 'success', 'message' => trans('auth.captcha_send')]

+ 3 - 2
app/Http/Controllers/Gateway/F2Fpay.php

@@ -2,6 +2,7 @@
 
 namespace App\Http\Controllers\Gateway;
 
+use App\Components\IP;
 use App\Models\Payment;
 use Auth;
 use Exception;
@@ -116,10 +117,10 @@ class F2Fpay extends AbstractPayment
                     }
                 }
             } else {
-                Log::info('支付宝当面付-POST:交易失败[' . getClientIp() . ']');
+                Log::info('支付宝当面付-POST:交易失败[' . IP::getClientIp() . ']');
             }
         } else {
-            Log::info('支付宝当面付-POST:验证失败[' . getClientIp() . ']');
+            Log::info('支付宝当面付-POST:验证失败[' . IP::getClientIp() . ']');
         }
 
         // 返回验证结果

+ 6 - 1
app/Http/Controllers/User/SubscribeController.php

@@ -2,6 +2,7 @@
 
 namespace App\Http\Controllers\User;
 
+use App\Components\IP;
 use App\Http\Controllers\Controller;
 use App\Models\UserSubscribe;
 use App\Models\UserSubscribeLog;
@@ -71,7 +72,11 @@ class SubscribeController extends Controller
         $subscribe->increment('times', 1);
 
         // 记录每次请求
-        $this->subscribeLog($subscribe->id, getClientIp(), $request->headers);
+        $this->subscribeLog(
+            $subscribe->id,
+            IP::getClientIp(),
+            $request->headers
+        );
 
         // 获取这个账号可用节点
         $query = $user->whereIsSubscribe(1)->userAccessNodes();

+ 40 - 66
app/Http/Middleware/isForbidden.php

@@ -3,8 +3,7 @@
 namespace App\Http\Middleware;
 
 use Agent;
-use App\Components\IPIP;
-use App\Components\QQWry;
+use App\Components\IP;
 use Closure;
 use Illuminate\Http\Request;
 use Log;
@@ -25,7 +24,7 @@ class isForbidden
     {
         // 拒绝机器人访问
         if (sysConfig('is_forbid_robot') && Agent::isRobot()) {
-            Log::info("识别到机器人访问(" . getClientIp() . ")");
+            Log::info("识别到机器人访问(" . IP::getClientIp() . ")");
 
             return Response::view(
                 'auth.error',
@@ -40,40 +39,16 @@ class isForbidden
                 sysConfig('subscribe_domain'),
                 sysConfig('website_url')
             )) {
-            Log::info("识别到通过订阅链接访问,强制跳转至百度(" . getClientIp() . ")");
+            Log::info("识别到通过订阅链接访问,强制跳转至百度(" . IP::getClientIp() . ")");
 
             return redirect('https://www.baidu.com');
         }
 
-        $ip = getClientIP();
-        if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
-            Log::info('识别到IPv6,尝试解析:' . $ip);
-            $isIPv6 = true;
-            $ipInfo = getIPInfo($ip);
-        } else {
-            $isIPv6 = false;
-            $ipInfo = QQWry::ip($ip); // 通过纯真IP库解析IPv4信息
-            if (isset($ipInfo['error'])) {
-                Log::info('无法识别IPv4,尝试使用IPIP的IP库解析:' . $ip);
-                $ipip   = IPIP::ip($ip);
-                $ipInfo = [
-                    'country'  => $ipip['country_name'],
-                    'province' => $ipip['region_name'],
-                    'city'     => $ipip['city_name'],
-                ];
-            } else {
-                // 判断纯真IP库获取的国家信息是否与IPIP的IP库获取的信息一致,不一致则用IPIP的(因为纯真IP库的非大陆IP准确率较低)
-                $ipip = IPIP::ip($ip);
-                if ($ipInfo['country'] != $ipip['country_name']) {
-                    $ipInfo['country']  = $ipip['country_name'];
-                    $ipInfo['province'] = $ipip['region_name'];
-                    $ipInfo['city']     = $ipip['city_name'];
-                }
-            }
-        }
+        $ip         = IP::getClientIP();
+        $ipLocation = IP::getIPInfo($ip);
 
         // 拒绝无IP请求
-        if (empty($ipInfo) || empty($ipInfo['country'])) {
+        if (empty($ipLocation) || empty($ipLocation['city'])) {
             return Response::view(
                 'auth.error',
                 ['message' => trans('error.ForbiddenAccess')],
@@ -81,47 +56,46 @@ class isForbidden
             );
         }
 
-        if ( ! in_array($ipInfo['country'], ['本机地址', '局域网'])) {
+        if ( ! in_array($ipLocation['country'], ['本机地址', '局域网'])) {
             // 拒绝大陆IP访问
-            if (sysConfig('is_forbid_china')) {
-                if (($isIPv6 && $ipInfo['country'] === 'China')
-                    || ($ipInfo['country'] === '中国'
-                        && ! in_array(
-                            $ipInfo['province'],
-                            ['香港', '澳门', '台湾']
-                        ))) {
-                    Log::info('识别到大陆IP,拒绝访问:' . $ip);
+            if (sysConfig('is_forbid_china') &&
+                in_array($ipLocation['country'], ['China', '中国']) &&
+                ! in_array(
+                    $ipLocation['province'],
+                    ['香港', '澳门', '台湾', '台湾省']
+                )) {
+                Log::info('识别到大陆IP,拒绝访问:' . $ip);
 
-                    return Response::view(
-                        'auth.error',
-                        [
-                            'message' => trans(
-                                'error.ForbiddenChina'
-                            ),
-                        ],
-                        403
-                    );
-                }
+                return Response::view(
+                    'auth.error',
+                    [
+                        'message' => trans(
+                            'error.ForbiddenChina'
+                        ),
+                    ],
+                    403
+                );
             }
 
             // 拒绝非大陆IP访问
-            if (sysConfig('is_forbid_oversea')) {
-                if (($isIPv6 && $ipInfo['country'] !== 'China') || $ipInfo['country'] !== '中国'
-                    || in_array($ipInfo['province'], ['香港', '澳门', '台湾'])) {
-                    Log::info(
-                        '识别到海外IP,拒绝访问:' . $ip . ' - ' . $ipInfo['country']
-                    );
+            if (sysConfig('is_forbid_oversea')
+                && ! in_array(
+                    $ipLocation['country'],
+                    ['China', '中国', 'Taiwan', 'Hong Kong', 'Macao']
+                )) {
+                Log::info(
+                    '识别到海外IP,拒绝访问:' . $ip . ' - ' . $ipLocation['country']
+                );
 
-                    return Response::view(
-                        'auth.error',
-                        [
-                            'message' => trans(
-                                'error.ForbiddenOversea'
-                            ),
-                        ],
-                        403
-                    );
-                }
+                return Response::view(
+                    'auth.error',
+                    [
+                        'message' => trans(
+                            'error.ForbiddenOversea'
+                        ),
+                    ],
+                    403
+                );
             }
         }
 

+ 2 - 1
app/Http/Middleware/isSecurity.php

@@ -2,6 +2,7 @@
 
 namespace App\Http\Middleware;
 
+use App\Components\IP;
 use Cache;
 use Closure;
 use Log;
@@ -20,7 +21,7 @@ class isSecurity
      */
     public function handle($request, Closure $next)
     {
-        $ip                  = getClientIP();
+        $ip                  = IP::getClientIP();
         $code                = $request->securityCode;
         $cacheKey            = 'SecurityLogin_' . ip2long($ip);
         $websiteSecurityCode = sysConfig('website_security_code');

+ 2 - 1
app/Services/NodeService.php

@@ -2,6 +2,7 @@
 
 namespace App\Services;
 
+use App\Components\IP;
 use App\Models\Node;
 use App\Models\NodeLabel;
 
@@ -18,7 +19,7 @@ class NodeService
 
         $result = 0;
         foreach ($nodes as $node) {
-            $data = getIPInfo(
+            $data = IP::IPSB(
                 $node->is_ddns ? gethostbyname($node->server) : $node->ip
             );
             if ($data) {

+ 0 - 58
app/helpers.php

@@ -1,7 +1,6 @@
 <?php
 
 use App\Components\Helpers;
-use GuzzleHttp\Client;
 
 define('KB', 1024);
 define('MB', 1048576);
@@ -114,63 +113,6 @@ if ( ! function_exists('seconds2time')) {
     }
 }
 
-// 获取访客真实IP
-if ( ! function_exists('getClientIP')) {
-    function getClientIP()
-    {
-        /*
-         * 访问时用localhost访问的,读出来的是“::1”是正常情况
-         * ::1说明开启了IPv6支持,这是IPv6下的本地回环地址的表示
-         * 使用IPv4地址访问或者关闭IPv6支持都可以不显示这个
-         */
-        if (isset($_SERVER)) {
-            if (isset($_SERVER['HTTP_CF_CONNECTING_IP'])) {
-                $_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_CF_CONNECTING_IP'];
-                $ip                     = $_SERVER['REMOTE_ADDR'];
-            } elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
-                $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
-            } elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {
-                $ip = $_SERVER['HTTP_CLIENT_IP'];
-            } elseif (isset($_SERVER['REMOTE_ADDR'])) {
-                $ip = $_SERVER['REMOTE_ADDR'];
-            } else {
-                $ip = 'unknown';
-            }
-        } elseif (getenv('HTTP_X_FORWARDED_FOR')) {
-            $ip = getenv('HTTP_X_FORWARDED_FOR');
-        } elseif (getenv('HTTP_CLIENT_IP')) {
-            $ip = getenv('HTTP_CLIENT_IP');
-        } else {
-            $ip = getenv('REMOTE_ADDR');
-        }
-
-        if (trim($ip) === '::1') {
-            $ip = '127.0.0.1';
-        }
-
-        return $ip;
-    }
-}
-
-// 获取IPv6信息
-if ( ! function_exists('getIPInfo')) {
-    function getIPInfo($ip)
-    {
-        $request = (new Client(['timeout' => 15]))->get(
-            'https://api.ip.sb/geoip/' . $ip
-        );
-        $message = json_decode($request->getBody(), true);
-
-        if ($request->getStatusCode() == 200) {
-            return $message;
-        }
-
-        Log::error('解析IPv6异常:' . $ip . PHP_EOL . var_export($request, true));
-
-        return false;
-    }
-}
-
 // 过滤emoji表情
 if ( ! function_exists('filterEmoji')) {
     function filterEmoji($str)

+ 5 - 3
composer.json

@@ -13,14 +13,15 @@
     "ext-openssl": "*",
     "fideloper/proxy": "^4.2",
     "fruitcake/laravel-cors": "^2.0",
+    "geoip2/geoip2": "^2.10",
     "guzzlehttp/guzzle": "^6.3",
+    "ip2location/ip2location-laravel": "^1.2",
     "ipip/db": "^1.0",
-    "itbdw/ip-database": "^2.0",
     "jenssegers/agent": "^2.6",
     "laravel/framework": "^7.24",
     "laravel/tinker": "^2.0",
     "mews/captcha": "^3.1",
-    "mews/purifier": "^3.2",
+    "mews/purifier": "^3.3",
     "openlss/lib-array2xml": "^1.0",
     "overtrue/laravel-lang": "^4.0",
     "phpoffice/phpspreadsheet": "^1.14",
@@ -32,7 +33,8 @@
     "xhat/payjs": "^1.4",
     "zbrettonye/geetest": "^1.1",
     "zbrettonye/hcaptcha": "^1.0",
-    "zbrettonye/no-captcha": "^1.0"
+    "zbrettonye/no-captcha": "^1.0",
+    "zoujingli/ip2region": "^1.0"
   },
   "require-dev": {
     "barryvdh/laravel-debugbar": "^3.4",

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 433 - 144
composer.lock


Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio