我正在尝试使用MySQL在我的网络应用程序中实现IP禁止系统,我知道我可以使用它,.htaccess但这不是我的整洁.
基本上我目前的表是:
ip_blacklist(id, ip, date)
Run Code Online (Sandbox Code Playgroud)
在php中我查找数据库中的客户端IP以查看它是否被阻止:
$sql = "SELECT ip FROM ip_blacklist WHERE ip = ? LIMIT 1"
$query = $this->db->query($sql, array($ip));
if($query->num_rows() > 0){
// Gotcha
}
Run Code Online (Sandbox Code Playgroud)
现在..这工作正常,但我希望能够在数据库中输入通配符IP范围,如:
42.21.58.*
42.21.*.*
53.*.*.*
Run Code Online (Sandbox Code Playgroud)
怎么做?
提前致谢.
如果您将始终一次检查一个IP地址并且禁止的范围永远不会相交,则应以数字格式存储禁止范围的起始和结束地址.
再说了,你要禁止192.168.1.0到192.168.1.15这192.168.1.0/28.
你创建一个这样的表:
CREATE TABLE ban (start_ip INT UNSIGNED NOT NULL PRIMARY KEY, end_ip INT UNSIGNED NOT NULL)
Run Code Online (Sandbox Code Playgroud)
,在那里插入范围:
INSERT
INTO ban
VALUES (INET_ATON('192.168.1.0'), INET_ATON('192.168.1.0') + POWER(2, 32 - 28) - 1)
Run Code Online (Sandbox Code Playgroud)
然后检查:
SELECT (
SELECT end_ip
FROM ban
WHERE start_ip <= INET_ATON('192.168.1.14')
ORDER BY
start_ip DESC
LIMIT 1
) >= INET_ATON('192.168.1.14')
Run Code Online (Sandbox Code Playgroud)
在ORDER BY与LIMIT部分所需的查询是有效的.
如前所述,这一次假定非交叉块和一个IP.
如果阻滞相交(例如,你禁止192.168.1.0/28并192.168.1.0/24在同一时间),查询可能返回假阴性.
如果您想一次查询多个IP(例如,更新具有长IP地址列表的表),那么此查询将是低效的(MySQL不会range在相关子查询中进行优化)
在这两种情况下,您都需要将范围存储为LineString空间索引并使用空间索引进行快速搜索:
CREATE TABLE ban (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, range LINESTRING NOT NULL) ENGINE=MyISAM;
CREATE SPATIAL INDEX sx_ban_range ON ban (range);
INSERT
INTO ban (range)
VALUES (
LineString
(
Point(INET_ATON('192.168.1.0'), -1),
Point(INET_ATON('192.168.1.0') + POWER(2, 32 - 28) - 1), 1)
)
);
SELECT *
FROM ban
WHERE MBRContains(range, Point(INET_ATON('192.168.1.14'), 0))
Run Code Online (Sandbox Code Playgroud)