first commit
This commit is contained in:
58
src/Shared/Http/ClientIpResolver.php
Normal file
58
src/Shared/Http/ClientIpResolver.php
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Shared\Http;
|
||||
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
/**
|
||||
* Résout l'adresse IP cliente à partir de la requête HTTP.
|
||||
*
|
||||
* L'en-tête X-Forwarded-For n'est pris en compte que si REMOTE_ADDR
|
||||
* correspond à un proxy explicitement approuvé. En l'absence d'IP
|
||||
* exploitable, la valeur de repli '0.0.0.0' est renvoyée.
|
||||
*/
|
||||
final class ClientIpResolver
|
||||
{
|
||||
/**
|
||||
* @param string[] $trustedProxies
|
||||
*/
|
||||
public function __construct(private readonly array $trustedProxies = [])
|
||||
{
|
||||
}
|
||||
|
||||
public function resolve(ServerRequestInterface $request): string
|
||||
{
|
||||
$serverParams = $request->getServerParams();
|
||||
$remoteAddr = trim((string) ($serverParams['REMOTE_ADDR'] ?? ''));
|
||||
|
||||
if ($remoteAddr === '') {
|
||||
return '0.0.0.0';
|
||||
}
|
||||
|
||||
if (!$this->isTrustedProxy($remoteAddr)) {
|
||||
return $remoteAddr;
|
||||
}
|
||||
|
||||
$forwarded = trim((string) ($serverParams['HTTP_X_FORWARDED_FOR'] ?? ''));
|
||||
|
||||
if ($forwarded === '') {
|
||||
return $remoteAddr;
|
||||
}
|
||||
|
||||
$candidate = trim(explode(',', $forwarded)[0]);
|
||||
|
||||
return filter_var($candidate, FILTER_VALIDATE_IP) ? $candidate : $remoteAddr;
|
||||
}
|
||||
|
||||
private function isTrustedProxy(string $remoteAddr): bool
|
||||
{
|
||||
foreach ($this->trustedProxies as $proxy) {
|
||||
if ($proxy === '*' || $proxy === $remoteAddr) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user