Validar Ip Dentro Da Faixa De Ip
#1
Posted 07/08/2008, 17:30
imaginem um cadastro onde o usuario entra com um ip:
189.12.125.12
Eu preciso validar este ip que o usuario entrou perante a uma base de dados que contém faixas
de ips cadastrados, ou seja, preciso saber se este IP está dentro de uma dessa faixas de ips,
como poderia fazer isso?
Base de dados contendo faixas de ip
Faixa Inicial Faixa Final
1. 189.12.0.0 - 189.13.255.255
2. 189.24.0.0 - 189.25.255.255
3. 189.48.0.0 - 189.49.255.255
4. 189.70.0.0 - 189.70.255.255
#2
Posted 07/08/2008, 17:53
#3
Posted 07/08/2008, 18:45
<?php
function checaIP($qual,$inicio,$final){
$sub = explode(".",$qual);
//rotinas para verificar se é um ip válido...
if(count($sub) != 4){
return array(false,"IP Inválido");
}
for($i = 0; $i < count($sub); $i++){
if($sub[$i] < 0 || $sub[$i] > 255 || !is_numeric($sub[$i])){
return array(false,"IP Inválido");
}
}
$ini = explode(".",$inicio);
//rotinas para verificar se é um ip válido...
if(count($ini) != 4){
return array(false,"Faixa inicial inválida");
}
for($i = 0; $i < count($ini); $i++){
if($ini[$i] < 0 || $ini[$i] > 255 || !is_numeric($ini[$i])){
return array(false,"Faixa inicial inválida");
}
}
$fim = explode(".",$final);
//rotinas para verificar se é um ip válido...
if(count($fim) != 4){
return array(false,"Faixa final inválida");
}
for($i = 0; $i < count($fim); $i++){
if($fim[$i] < 0 || $fim[$i] > 255 || !is_numeric($fim[$i])){
return array(false,"Faixa inicial inválida");
}
}
// verificar se as faixas estao corretas
if($ini[0]> $fim[0]){
return array(false,"Faixa inicial deve ser menor que faixa final");
}
if($ini[1]> $fim[1] && $ini[0] == $fim[0]){
return array(false,"Faixa inicial deve ser menor que faixa final");
}
if($ini[2]> $fim[2] && $ini[0] == $fim[0] && $ini[1] == $fim[1]){
return array(false,"Faixa inicial deve ser menor que faixa final");
}
if($ini[3]> $fim[3] && $ini[0] == $fim[0] && $ini[1] == $fim[1] && $ini[2] == $fim[2]){
return array(false,"Faixa inicial deve ser menor que faixa final");
}
//enfim verifica se o ip passado está dentro desta faixa...
if($sub[0] < $ini[0] || $sub[0] > $fim[0]){
return array(false,"IP fora da faixa");
}
if($sub[1] < $ini[1] || $sub[1] > $fim[1]){
if($sub[0] >! $fim[0] || $sub[0] <! $ini[0]){
return array(false,"IP Fora da Faixa");
}
}
if($sub[2] < $ini[2] || $sub[2] > $fim[2]){
if($sub[1] >! $fim[1] || $sub[1] <! $ini[1]){
if($sub[0] >! $fim[0] || $sub[0] <! $ini[0]){
return array(false,"FaixaIP Fora da Faixa");
}
}
}
if($sub[3] < $ini[3] || $sub[3] > $fim[3]){
if($sub[2] >! $fim[2] || $sub[2] <! $ini[2]){
if($sub[1] >! $fim[1] || $sub[1] <! $ini[1]){
if($sub[0] >! $fim[0] || $sub[0] <! $ini[0]){
return array(false,"IP Fora da Faixa");
}
}
}
}
return array(true);
}
//Exemplo...
$ip = array("192.168.0.1","192.168.1.1","192.168.255.255","192.168.0.0","0.0.0.0","192.168.0.0",
"192.168.0.255","192.255.0.0","255.168.0.1","192.0.0.0");
$inicio = "192.168.0.0";
$fim = "192.168.0.255";
foreach($ip as $pk){
$teste = checaIp($pk,$inicio,$fim);
if($teste[0] == false){
echo("erro: ". $teste[1] ."; IP: $pk; Inicio: $inicio; Fim: $fim<br />");
} else {
echo("Certo... IP: $pk; Inicio: $inicio; Fim: $fim <br />");
}
}
?>vlw...
#4
Posted 07/08/2008, 18:47
integer do PHP é signed. Isto faz com que a função gere valores negativos para determinados endereços. Mas deixe-me te tacar uma idéia... Ao invés de ter um campo
faixa_inicial e faixa_final no banco de dados, porque não usa um campo só usando o padrão CIDR?Dê uma lida aqui: http://en.wikipedia....-Domain_Routing
Tomando a primeira faixa (189.12.0.0 - 189.13.255.255) como exemplo, ficaria: 189.12.0.0/15
Aí você poderia usar esta função, contida nesta mesma página do manual:
function netMatch($cidr, $ip)
{
list($net, $mask) = explode ('/', $cidr);
return (ip2long($ip) & ~((1 << (32 - $mask)) - 1)) == ip2long($net);
}Para usá-la:
print netMatch('189.12.0.0/15', '189.12.125.12') ? 'dentro da faixa especificada'
: 'fora da faixa especificada';[]s
#5
Posted 07/08/2008, 20:50
Só atente-se que o tipo
integerdo PHP ésigned. Isto faz com que a função gere valores negativos para determinados endereços.
Mas deixe-me te tacar uma idéia... Ao invés de ter um campofaixa_inicialefaixa_finalno banco de dados, porque não usa um campo só usando o padrão CIDR?
Dê uma lida aqui: http://en.wikipedia....-Domain_Routing
Tomando a primeira faixa (189.12.0.0 - 189.13.255.255) como exemplo, ficaria: 189.12.0.0/15
Aí você poderia usar esta função, contida nesta mesma página do manual:function netMatch($cidr, $ip) { list($net, $mask) = explode ('/', $cidr); return (ip2long($ip) & ~((1 << (32 - $mask)) - 1)) == ip2long($net); }
Para usá-la:print netMatch('189.12.0.0/15', '189.12.125.12') ? 'dentro da faixa especificada' : 'fora da faixa especificada';[]’s
boa... vou dar uma testada e funcionando direito mando meu script embora...
#6
Posted 07/08/2008, 22:45
Bem, eu gerei todos os IP's desta faixa via script e inseri mais alguns outros inválidos num arquivo. Fiz o teste e somente os inválidos retornaram falso. Com isso creio que esteja totalmente funcional.boa... vou dar uma testada e funcionando direito mando meu script embora...
:D vlw
A propósito, se você estiver usando MySQL, pode fazer diretamente da consulta:
SELECT INET_ATON(ip) & ~((1 << (32 - SUBSTRING_INDEX(cidr, '/', -1))) - 1) = INET_ATON(SUBSTRING_INDEX(cidr, '/', 1))A consulta retorna
1 quando verdadeiro e 0 quando falso.[]s
1 user(s) are reading this topic
0 membro(s), 1 visitante(s) e 0 membros anônimo(s)










