feature #32194 [HttpFoundation] Add a way to anonymize IPs (Seldaek)
This PR was merged into the 4.4 branch.
Discussion
----------
[HttpFoundation] Add a way to anonymize IPs
| Q | A
| ------------- | ---
| Branch? | 4.4
| Bug fix? | no
| New feature? | yes
| BC breaks? | no
| Deprecations? | no
| Tests pass? | yes
| Fixed tickets |
| License | MIT
| Doc PR | symfony/symfony-docs#... <!-- required for new features --> TODO
This is helpful for GDPR compliance reasons, and it isn't much code saved but it's also good if you don't have to think about how to do it.
Commits
-------
9e62330bc4
[HttpFoundation] Add a way to anonymize IPs
This commit is contained in:
commit
f4c925418b
|
@ -11,7 +11,8 @@ CHANGELOG
|
|||
make sure to run `CREATE INDEX EXPIRY ON sessions (sess_lifetime)` to update your database
|
||||
to speed up garbage collection of expired sessions.
|
||||
* added `SessionHandlerFactory` to create session handlers with a DSN
|
||||
|
||||
* added `IpUtils::anonymize()` to help with GDPR compliance.
|
||||
|
||||
4.3.0
|
||||
-----
|
||||
|
||||
|
|
|
@ -153,4 +153,36 @@ class IpUtils
|
|||
|
||||
return self::$checkedIps[$cacheKey] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Anonymizes an IP/IPv6.
|
||||
*
|
||||
* Removes the last byte for v4 and the last 8 bytes for v6 IPs
|
||||
*/
|
||||
public static function anonymize(string $ip): string
|
||||
{
|
||||
$wrappedIPv6 = false;
|
||||
if ('[' === substr($ip, 0, 1) && ']' === substr($ip, -1, 1)) {
|
||||
$wrappedIPv6 = true;
|
||||
$ip = substr($ip, 1, -1);
|
||||
}
|
||||
|
||||
$packedAddress = inet_pton($ip);
|
||||
if (4 === \strlen($packedAddress)) {
|
||||
$mask = '255.255.255.0';
|
||||
} elseif ($ip === inet_ntop($packedAddress & inet_pton('::ffff:ffff:ffff'))) {
|
||||
$mask = '::ffff:ffff:ff00';
|
||||
} elseif ($ip === inet_ntop($packedAddress & inet_pton('::ffff:ffff'))) {
|
||||
$mask = '::ffff:ff00';
|
||||
} else {
|
||||
$mask = 'ffff:ffff:ffff:ffff:0000:0000:0000:0000';
|
||||
}
|
||||
$ip = inet_ntop($packedAddress & inet_pton($mask));
|
||||
|
||||
if ($wrappedIPv6) {
|
||||
$ip = '['.$ip.']';
|
||||
}
|
||||
|
||||
return $ip;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -101,4 +101,30 @@ class IpUtilsTest extends TestCase
|
|||
'invalid request IP with invalid proxy wildcard' => ['0.0.0.0', '*'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider anonymizedIpData
|
||||
*/
|
||||
public function testAnonymize($ip, $expected)
|
||||
{
|
||||
$this->assertSame($expected, IpUtils::anonymize($ip));
|
||||
}
|
||||
|
||||
public function anonymizedIpData()
|
||||
{
|
||||
return [
|
||||
['192.168.1.1', '192.168.1.0'],
|
||||
['1.2.3.4', '1.2.3.0'],
|
||||
['2a01:198:603:0:396e:4789:8e99:890f', '2a01:198:603::'],
|
||||
['2a01:198:603:10:396e:4789:8e99:890f', '2a01:198:603:10::'],
|
||||
['::1', '::'],
|
||||
['0:0:0:0:0:0:0:1', '::'],
|
||||
['1:0:0:0:0:0:0:1', '1::'],
|
||||
['0:0:603:50:396e:4789:8e99:0001', '0:0:603:50::'],
|
||||
['[0:0:603:50:396e:4789:8e99:0001]', '[0:0:603:50::]'],
|
||||
['[2a01:198::3]', '[2a01:198::]'],
|
||||
['::ffff:123.234.235.236', '::ffff:123.234.235.0'], // IPv4-mapped IPv6 addresses
|
||||
['::123.234.235.236', '::123.234.235.0'], // deprecated IPv4-compatible IPv6 address
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
Reference in New Issue