bespredel/geo-restrict 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

bespredel/geo-restrict

Composer 安装命令:

composer require bespredel/geo-restrict

包简介

Middleware to restrict access to Laravel applications based on IP geolocation.

README 文档

README

Readme EN Readme RU GitHub license Downloads

Latest Version Latest Version Packagist PHP from Packagist Laravel Version

🚀 Production-ready GeoIP access control for Laravel applications

GeoRestrict is a powerful and flexible Laravel middleware that allows you to control access to your application based on user geolocation.

It supports filtering by country, region, city, ASN, ISP, and provides advanced features like multi-provider fallback, caching, rate limiting, and flexible rule configuration.

✨ Features

  • 🌍 Geo-based filtering (country, region, city, ASN, ISP)
  • 🔀 Multiple GeoIP providers with fallback support
  • ⚡ Built-in caching for performance optimization
  • 🚦 Rate limiting for external GeoIP services
  • 🧠 Flexible allow/deny rules with callbacks
  • ⏱ Time-based access restrictions
  • 📍 Route-level targeting (patterns + HTTP methods)
  • 🛡 IP whitelist support
  • 🌐 Multi-language error responses
  • 📊 Logging for allowed and blocked requests

📦 Installation

  1. Install the package via Composer::
composer require bespredel/geo-restrict
  1. Publish the config file:
php artisan vendor:publish --provider="Bespredel\GeoRestrict\GeoRestrictServiceProvider" --tag=geo-restrict-config
  1. (Optional) Publish language files for customization:
php artisan vendor:publish --provider="Bespredel\GeoRestrict\GeoRestrictServiceProvider" --tag=geo-restrict-lang

⚙️ Configuration

The configuration file allows you to fully customize how GeoRestrict behaves.

Example:

return [
    'services' => [
        // Example provider with options
        [
            'provider' => \Bespredel\GeoRestrict\Providers\Ip2LocationIoProvider::class,
            'options'  => [
                'api_key' => 'your-ip2location-api-key', // required
                'lang'    => 'en', // optional
            ],
        ],

        // Example provider without options
        \Bespredel\GeoRestrict\Providers\IpWhoIsProvider::class,

        // or
        [
            'provider' => \Bespredel\GeoRestrict\Providers\IpWhoIsProvider::class,
            'options'  => [],
        ],

        // Example array provider
        [
            'name' => 'ipapi.co',
            'url'  => 'https://ipapi.co/:ip/json/',
            'headers' => [
                'Accept' => 'application/json',
            ],
            'map'  => [
                'country' => 'country_code',
                'region'  => 'region_code',
                'city'    => 'city',
                'asn'     => 'asn',
                'isp'     => 'org',
            ],
        ],

        // Add more services; priority is based on order
    ],

    'geo_services' => [
        'cache_ttl'  => 1440,
        'rate_limit' => 30,
        'provider_timeout' => 5,
        'provider_retries' => 0,
        'provider_retry_delay_ms' => 150,
    ],

    'access' => [
        'rules' => [
            'allow' => [
                'country'  => ['RU'],
                'region'   => [],
                'city'     => [],
                'asn'      => [],
                'callback' => null, // function($geo) { return ...; }
                'time'     => [
                    // ['from' => '08:00', 'to' => '20:00']
                ],
            ],
            'deny'  => [
                'country'  => [],
                'region'   => [],
                'city'     => [],
                'asn'      => [],
                'callback' => null, // function($geo) { return ...; }
                'time'     => [
                    // ['from' => '22:00', 'to' => '06:00']
                ],
            ],
        ],
    ],
    
    'routes' => [
        'only'    => [], // ['admin/*', 'api/v1/*']
        'except'  => [],
        'methods' => [], // ['GET', 'POST']
    ],
    
    'excluded_networks' => [
        '127.0.0.1',
        '::1',
        '10.0.0.0/8',
        '192.168.0.0/16',
        '172.16.0.0/12',
        // Add more as needed
    ],

    'logging' => [
        'blocked_requests' => true,
        'allowed_requests' => false,
        'channel' => 'geo-restrict', // Use your custom channel name
    ],

    'observability' => [
        'log_cache_hits' => false,
        'log_provider_latency' => false,
        'log_deny_reasons' => false,
    ],

    'block_response' => [
        'type'  => 'abort', // 'abort', 'json', 'view'
        'view'  => 'errors.geo_blocked',
        'json'  => [
            'message' => 'Access denied: your region is restricted.',
        ],
    ]
];

Key parameters explained

  • services - list of geo-services used to resolve location by IP. Each provider supports only its documented parameters (see table below).
  • geo_services.cache_ttl - cache lifetime in minutes (0 disables caching).
  • geo_services.rate_limit - max requests per minute per IP to geo services.
  • geo_services.provider_timeout/provider_retries - provider timeout and retry policy.
  • access.rules.allow/deny - allow/deny rules by country, region, ASN, callbacks and time periods.
  • logging - enable logging of blocked or allowed requests.
  • observability - optional debug diagnostics for cache hits, latency and deny reasons.
  • block_response.type - response type: 'abort', 'json', or 'view'.
  • routes.only/except/methods - route and method matching.
  • excluded_networks - list of IP networks to exclude from geo restriction.

Supported Providers and Parameters

Provider Class Required Params Optional Params
IP2Location.io Ip2LocationIoProvider api_key, ip lang
ipwho.is IpWhoIsProvider ip api_key
ip-api.com IpApiComProvider ip lang
ipapi.co IpApiCoProvider ip lang

Only parameters listed in requiredParams and optionalParams for each provider will be used in the request. If a required parameter is missing, an error will be thrown and logged. Optional parameters are included only if set in config.

Provider architecture

All geo providers now inherit from AbstractGeoProvider and only need to define:

  • baseUrl, endpoint (with :param placeholders)
  • requiredParams, optionalParams
  • responseMap (array for mapping API fields to standard keys)
  • isValidResponse(array $data) (checks if API response is valid)
  • getErrorMessage(array $data) (returns error message for invalid response)

Example of a minimal provider:

class ExampleProvider extends AbstractGeoProvider {
    protected ?string $baseUrl = 'https://example.com/';
    protected ?string $endpoint = 'api/:ip';
    protected array $requiredParams = ['ip'];
    protected array $optionalParams = ['lang'];
    protected array $responseMap = [
        'country' => 'country_code',
        'region'  => 'region',
        'city'    => 'city',
        'asn'     => 'asn',
        'isp'     => 'isp',
    ];
    protected function isValidResponse(array $data): bool {
        return isset($data['country_code']);
    }
    protected function getErrorMessage(array $data): string {
        return 'example.com: invalid response';
    }
    public function getName(): string { return 'example.com'; }
}

This makes it easy to add new providers and ensures all logic is unified and DRY.

Compatibility notes

  • GeoAccess::passesRules() is still available for backward compatibility.
  • New code can use GeoAccess::evaluateRules() for a structured rule-check result.

🚀 Usage

  1. Add the middleware to routes:
Route::middleware(['geo-restrict'])->group(function () {
    // ...
});
  1. Or apply directly:
Route::get('/secret', 'SecretController@index')->middleware('geo-restrict');

🔧 Customization

  • Add your geo-services to the services array; order defines priority.
  • Use allow/deny rules for flexible filtering.
  • For complex cases, use callback functions in rules.
  • For localization, use language files.

🌐 Localization and Language Files

GeoRestrict supports multi-language block messages. To customize or add new translations:

  1. Publish the language files:
php artisan vendor:publish --provider="Bespredel\GeoRestrict\GeoRestrictServiceProvider" --tag=geo-restrict-lang
  1. Edit files in resources/lang/vendor/geo-restrict/ as needed. Add new locales by creating new folders (e.g., it, es).
  • The block message is automatically shown in the user's country language (based on the country code, if a corresponding language file exists), or in the application's default language.
  • To add a new language, create a file like:
resources/lang/it/messages.php

No code changes are required - the language is detected automatically based on the country code (e.g., IT, FR, DE, RU, EN, etc.).

⚡ Cache Management & Tag-based Cache Flush

GeoRestrict uses Laravel's cache for geo-data and rate limiting. If your cache driver supports tags (Redis, Memcached), all geoip cache entries are tagged with geoip.

  • To flush all geoip cache entries at once, use the artisan command:
php artisan geo-restrict:clear-cache

You will see:

GeoIP cache flushed.

Note: Tag-based cache flush is only available for Redis and Memcached drivers. For other drivers, cache will not be flushed in bulk.

📊 Logging: Custom Channel Support

GeoRestrict supports logging to a custom channel. By default, all logs (blocked/allowed requests, provider errors, rate limits) go to the main Laravel log. To use a separate channel, set the logging.channel parameter in your config/geo-restrict.php:

'logging' => [
    'blocked_requests' => true,
    'allowed_requests' => false,
    'channel' => 'geo-restrict', // Use your custom channel name
],

Add a channel to your config/logging.php:

'channels' => [
    // ...
    'geo-restrict' => [
        'driver' => 'single',
        'path' => storage_path('logs/geo-restrict.log'),
        'level' => 'info',
    ],
],

If channel is not set or is null, logs will go to the default log channel.

📄 License

This package is open-source software licensed under the MIT license.

⭐ Support

If you find this package useful, consider giving it a star ⭐ on GitHub.

bespredel/geo-restrict 适用场景与选型建议

bespredel/geo-restrict 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 20 次下载、GitHub Stars 达 2, 最近一次更新时间为 2025 年 06 月 24 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「geo」 「geoip」 「access」 「middleware」 「laravel」 「location」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 bespredel/geo-restrict 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 bespredel/geo-restrict 我们能提供哪些服务?
定制开发 / 二次开发

基于 bespredel/geo-restrict 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 20
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 2
  • 点击次数: 30
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 2
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2025-06-24