2013-06-20 36 views
0

我試圖阻止某些IP地址和IP範圍執行某些操作。現在,我SELECT * FROM blocked WHERE ip=$_SERVER['REMOTE_ADDR'],如果 - > num_rows返回> 0,我重定向用戶。查詢返回匹配一個IP地址塊的行嗎?

這適用於全IP地址,但如果我把199.90.*.*例如,到數據庫中,我怎麼可能匹配?另外,將IP存儲在數據庫中的最佳方式是什麼?

回答

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)

0

我會首先檢查完整的IP地址,然後屏蔽掉帶*號的最後一個字節,並檢查這一點,那麼最後2個字節,依此類推。通過這種方式,您可以從具體到不那麼具體,並且如果一旦遇到問題,IP就會被阻止。這可能不是最有效的方式,但我想你只能在登錄時只做一次。

我將存儲的IP地址爲簡單起見字符串。

另一種解決方案可能是存儲IP地址作爲字節數組,但不會做任何事情更容易我猜想,並會與例如命令行工具SQL工具維護的要少得多。

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). 

當我想到,儲存的IPv4的最佳方式在MySQL數據地址基地正在使用該功能,將它們轉換爲int值並將其存儲。如果你想從它的int表示使用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)。

希望這有助於。