61 lines
1.6 KiB
PHP
61 lines
1.6 KiB
PHP
|
|
<?php
|
|||
|
|
|
|||
|
|
declare(strict_types=1);
|
|||
|
|
|
|||
|
|
namespace app\common\service;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 分流链接 IP 防护:开启时校验访客 IP 国家是否在链接投放国家列表内
|
|||
|
|
*/
|
|||
|
|
class SplitIpProtectService
|
|||
|
|
{
|
|||
|
|
/**
|
|||
|
|
* 是否允许继续轮转跳转
|
|||
|
|
*
|
|||
|
|
* @param int|string $ipProtect 链接 ip_protect:0=关闭,1=开启
|
|||
|
|
* @param string $countriesStorage 链接 countries 字段(ISO2 逗号分隔)
|
|||
|
|
* @param string $clientIp 访客 IP
|
|||
|
|
*/
|
|||
|
|
public static function isAllowed($ipProtect, string $countriesStorage, string $clientIp): bool
|
|||
|
|
{
|
|||
|
|
if ((int) $ipProtect !== 1) {
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
$allowed = self::parseAllowedCountries($countriesStorage);
|
|||
|
|
if ($allowed === []) {
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (!SplitGeoIpService::isDatabaseAvailable()) {
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
$visitorCountry = SplitGeoIpService::getCountryIso2($clientIp);
|
|||
|
|
if ($visitorCountry === null || $visitorCountry === '') {
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return in_array($visitorCountry, $allowed, true);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @return array<int, string> 大写 ISO2 列表
|
|||
|
|
*/
|
|||
|
|
public static function parseAllowedCountries(string $storage): array
|
|||
|
|
{
|
|||
|
|
if (trim($storage) === '') {
|
|||
|
|
return [];
|
|||
|
|
}
|
|||
|
|
$result = [];
|
|||
|
|
foreach (explode(',', $storage) as $code) {
|
|||
|
|
$code = strtoupper(trim($code));
|
|||
|
|
if ($code !== '' && !in_array($code, $result, true)) {
|
|||
|
|
$result[] = $code;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return $result;
|
|||
|
|
}
|
|||
|
|
}
|