查询返回与ip地址块匹配的行?

时间:2013-06-20 17:59:40

标签: php mysql mysqli

我正在尝试阻止某些IP地址和IP范围执行某些操作。现在,我SELECT * FROM blocked WHERE ip=$_SERVER['REMOTE_ADDR']和if - > num_rows返回> 0,我重定向用户。

这适用于完整的IP地址,但如果我将199.90.*.*放入数据库,我该如何匹配呢?另外,将IP存储在数据库中的最佳方法是什么?

3 个答案:

答案 0 :(得分:4)

您的问题的答案是使用like

SELECT *
FROM blocked
WHERE $_SERVER['REMOTE_ADDR'] like replace(ip, '*', '%')

like中的通配符是'%'而不是'*',因此这会将百分号替换为星号。我猜你实际上会存储像'199.199.%.%'这样的字符串,但上面的内容是为了清晰起见。

虽然这在技术上解决了您的问题,但还有其他问题,因为MySQL可能不会使用索引进行这些比较(请参阅here)。影响取决于被阻止的表的大小。如果它有100行,这可能不是问题。如果它有100,000,则可能是。

对被阻止的表使用通配符的替代方法是将FromIPToIP作为列。然后像“199.199。”这样的东西将简单地存储为“199.199.000.000”和“199.199.999.999”。查询将是:

where $_SERVER['REMOTE_ADDR'] between FromIP and ToIP

你会在blocked(FromIP, ToIP)上找到一个索引。

答案 1 :(得分:0)

我首先检查完整的IP地址,然后用*屏蔽最后一个字节,然后检查它,然后检查最后2个字节,依此类推。这样你就可以从具体到不太具体,如果一旦你受到打击,IP就会被阻止。它可能不是最有效的方式,但我想你必须在登录时只做一次。

为了简单起见,我会将IP地址存储为字符串。

另一个解决方案可能是将IP地址存储为字节数组,但我认为这样做不会更容易,并且使用命令行工具SQL工具可以更难维护。

答案 2 :(得分:0)

您最好的解决方案是使用INET_ATON功能。

将IPv4网络地址的虚线四边形表示为字符串,返回一个整数,表示网络字节顺序(大端)中地址的数值。

因此,如果您想在某个范围内查找IP,您可以使用如下查询:

SELECT * FROM blocked WHERE INET_ATON($_SERVER['REMOTE_ADDR']) between INET_ATON(this_ip) and INET_ATON(this_other_ip).

我认为,在MySQL数据库中存储IPv4地址的最佳方法是使用该函数,将它们转换为int值并将其存储起来。如果您想从int表示中获取IP,请使用INET_NTOA

将IP存储为int,查询结束如下:

SELECT * FROM blocked WHERE INET_ATON($_SERVER['REMOTE_ADDR']) between this_ip and this_other_ip.

而不是使用199.90。*。*使用(199.90.0.0)。

希望这有助于。