Pular para o conteúdo
← Voltar para projetos

Laravel Visitor Fingerprint

A zero-domain-knowledge visitor-fingerprinting toolkit for Laravel: device/browser/OS detection, IP anonymization, bot detection, GeoIP, VPN/proxy/Tor detection, and GDPR export/erasure

Laravel Visitor Fingerprint

#Laravel Visitor Fingerprint

Latest Version on Packagist GitHub Tests Action Status GitHub Code Style Action Status Total Downloads License

A zero-domain-knowledge visitor-fingerprinting toolkit for Laravel: given an HTTP request, safely identify device/browser/OS, anonymize/hash the IP, detect bots, resolve GeoIP, detect VPN/proxy/Tor, and support GDPR export/erasure. This package has no concept of "short URL" or "page visit" — those are concerns of the packages that consume it.

#Installation

You can install the package via composer:

composer require jeffersongoncalves/laravel-visitor-fingerprint

Optionally publish the config file:

php artisan vendor:publish --tag="visitor-fingerprint-config"

#Usage

#User agent, bot, language, referer

use JeffersonGoncalves\VisitorFingerprint\Facades\VisitorFingerprint;

VisitorFingerprint::deviceType($request->userAgent());     // 'desktop' | 'mobile' | 'tablet'
VisitorFingerprint::parseUserAgent($request->userAgent());  // ['browser' => 'Chrome', 'browser_version' => '128.0.0.0', 'operating_system' => 'Windows', 'operating_system_version' => '10.0']
VisitorFingerprint::isBot($request->userAgent());           // bool

VisitorFingerprint::preferredLanguage($request->header('Accept-Language'));  // 'en-US'
VisitorFingerprint::classifyReferer($request->header('Referer'), $request->getHost()); // 'social' | 'search' | 'email' | 'internal' | 'direct'

#IP anonymization and hashing

use JeffersonGoncalves\VisitorFingerprint\Support\IpAnonymizer;

IpAnonymizer::truncate($request->ip()); // '203.0.113.0' (IPv4 /24) or '2001:0db8:1234::' (IPv6 /48)
IpAnonymizer::hash($request->ip());     // salted sha256, safe to store for uniqueness comparisons
IpAnonymizer::version($request->ip());  // 4 or 6

#GeoIP

use JeffersonGoncalves\VisitorFingerprint\Facades\VisitorFingerprint;

$location = VisitorFingerprint::geoLocate($request->ip());
$location->country; $location->city; $location->latitude; $location->longitude;
$location->isp; $location->asn; // only populated by the ip_api driver, or the maxmind driver when an ASN database is configured (see below)

Driver is selected via visitor-fingerprint.geoip.driver: headers (trusts CDN-injected geo headers, e.g. Cloudflare/CloudFront — no isp/asn), ip_api (free-tier ip-api.com HTTP lookup, includes isp/asn), or maxmind (local MaxMind database, requires geoip2/geoip2).

The maxmind driver reads two separate MaxMind databases: GeoLite2-City (country/region/city/coordinates) has no ISP/ASN fields at all — those only exist in GeoLite2-ASN. Configure both paths and this package's own geoip:update command keeps them fresh:

php artisan geoip:update

Downloads and installs both editions with your MaxMind license key (visitor-fingerprint.geoip.maxmind_license_key, falls back to plain MAXMIND_LICENSE_KEY). Each edition is independent — a failure on one doesn't block the other from updating, and a failed run never touches the last-known-good file. Schedule it, e.g.:

// routes/console.php
Schedule::command('geoip:update')->weeklyOn(1, '02:00');

The ASN database is optional — without it (or with the headers/ip_api driver), isp/asn just stay null, same best-effort behavior as everything else in this package.

#VPN / proxy / Tor detection

use JeffersonGoncalves\VisitorFingerprint\Facades\VisitorFingerprint;

$threat = VisitorFingerprint::checkThreat($request->ip());
$threat->isVpn; $threat->isProxy; $threat->isTor; $threat->isDatacenter; $threat->confidence;

Driver is selected via visitor-fingerprint.vpn_detection.driver: ip_api or proxycheck. Both are best-effort — any lookup failure yields a "clean" result instead of raising, and results are cached per IP.

#GDPR / LGPD export and erasure

PersonalDataExporter is reusable against any consumer's own visit-like Eloquent model — this package has no model of its own:

use JeffersonGoncalves\VisitorFingerprint\Compliance\PersonalDataExporter;

$exporter = new PersonalDataExporter(\App\Models\Visit::class, ipHashColumn: 'ip_hash');

$exporter->exportForIp($ip);  // rows matching the hashed IP, as arrays
$exporter->forgetForIp($ip);  // nulls only the PII columns that exist on the model's table

#Configuration

// config/visitor-fingerprint.php
return [
    'hash_salt' => env('VISITOR_FINGERPRINT_HASH_SALT', config('app.key')),

    'geoip' => [
        'driver' => env('VISITOR_FINGERPRINT_GEOIP_DRIVER', 'headers'),
        'maxmind_database_path' => env('VISITOR_FINGERPRINT_MAXMIND_DB_PATH', storage_path('app/geoip/GeoLite2-City.mmdb')),
        'maxmind_asn_database_path' => env('VISITOR_FINGERPRINT_MAXMIND_ASN_DB_PATH', storage_path('app/geoip/GeoLite2-ASN.mmdb')),
        'maxmind_license_key' => env('VISITOR_FINGERPRINT_MAXMIND_LICENSE_KEY', env('MAXMIND_LICENSE_KEY')),
    ],

    'vpn_detection' => [
        'driver' => env('VISITOR_FINGERPRINT_VPN_DRIVER', 'ip_api'),
        'proxycheck_api_key' => env('VISITOR_FINGERPRINT_PROXYCHECK_API_KEY'),
        'cache_ttl' => env('VISITOR_FINGERPRINT_VPN_CACHE_TTL', 3600),
        'timeout' => env('VISITOR_FINGERPRINT_VPN_TIMEOUT', 2.0),
    ],
];

#Testing

composer test

#Changelog

Please see CHANGELOG for more information on what has changed recently.

#Contributing

Please see CONTRIBUTING for details.

#Security

If you discover any security related issues, please email the author instead of using the issue tracker.

#Credits

#License

The MIT License (MIT). Please see License File for more information.

Nova versão disponível.