60 lines
1.6 KiB
PHP
60 lines
1.6 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Service;
|
|
|
|
use App\Exception\MissingClientKeyException;
|
|
use Psr\Log\LoggerInterface;
|
|
use Symfony\Component\HttpFoundation\Request;
|
|
|
|
final class ClientKeyProvider
|
|
{
|
|
public function __construct(
|
|
private readonly LoggerInterface $logger,
|
|
) {
|
|
}
|
|
|
|
public function fromRequest(Request $request): string
|
|
{
|
|
$ip = $this->extractClientIp($request);
|
|
|
|
$clientKey = $this->hashIp($ip);
|
|
$this->logger->debug('Generated client key for request.', [
|
|
'client_key' => $clientKey,
|
|
]);
|
|
|
|
return $clientKey;
|
|
}
|
|
|
|
private function extractClientIp(Request $request): string
|
|
{
|
|
$forwarded = $request->headers->get('X-Forwarded-For');
|
|
if ($forwarded !== null && $forwarded !== '') {
|
|
$parts = array_filter(array_map('trim', explode(',', $forwarded)));
|
|
if ($parts !== []) {
|
|
$this->logger->info('Resolved client address from forwarded header.', [
|
|
'resolution' => 'forwarded',
|
|
]);
|
|
return $parts[0];
|
|
}
|
|
}
|
|
|
|
$ip = $request->getClientIp();
|
|
if (is_string($ip) && $ip !== '') {
|
|
$this->logger->info('Resolved client address from remote address.', [
|
|
'resolution' => 'remote',
|
|
]);
|
|
return $ip;
|
|
}
|
|
|
|
$this->logger->critical('Failed to resolve client address for key generation.');
|
|
throw new MissingClientKeyException();
|
|
}
|
|
|
|
private function hashIp(string $ip): string
|
|
{
|
|
return substr(hash('sha256', $ip), 0, 12);
|
|
}
|
|
}
|