Door
E Ander
op 18-01-2018 19:27
gewijzigd op 19-01-2018 13:52
3.403 views
Ik heb een database met ip adressen van mijn website bezoekers. Die IP adressen wil ik nu van land code en streek code voorzien en tevens of het een zoekmachine is of een bezoeker.
Inmiddels heb ik wat huiswerk gedaan en een database IP adressen van land, streek,eigenaar en soort code gemaakt.
Ik heb dus 2 databasevelden. 1)bezoekers en 2)iplandcoden.
Als ik nu van elke bezoeker uit 1) via 2 de bijbehorende gegevens zoek krijg ik als ik de database van 1) wil updaten een foutmelding.
Kan, wat ik in gedachten heb wel? Kan de data die je vergelijkt ook upgedate worden? En heeft iemand anders een voorbeeld hoe het wel kan?
Mijn script werkt tot het
<?php
// $ipvergelijk is een deel van het $ip adres. ipserver moet gelijk zijn aan het eerder gegeven $ip
$sqlc = "UPDATE inloggen SET land = 'United States' WHERE ipserver = $ip";
if(!$resc = mysqli_query($link, $sqlc))
{
echo "ip=".$ip."<br>";
//echo "link = ".$link."<br>";
trigger_error('Fout in query:'.mysqli_error());
mysqli_close($link);
//break 2;
}
?>
<?php
$sqlc = "
UPDATE inloggen
SET land = 'United States'
WHERE ipserver = '" . mysqli_real_escape_string($link, $ip) . "'
";
if ( ! $resc = mysqli_query($link, $sqlc)) {
echo "ip=" . $ip . "<br>";
trigger_error('Fout in query:' . mysqli_error());
mysqli_close($link);
}
?>
En dan bespaar ik je het verhaal over prepared statements. Maar dat zou je moeten lezen.
Voornaamste zaak is waarschijnlijk de realisatie dat het IP-adres een tekst (string) is, bestaande uit (mogelijk alfa)numerieke waarden, cijfers en andere symbolen. Om die reden zou deze waarde omvat moeten worden door quotes, die ontbreken in jouw oorspronkelijke codefragment.
Ook merkt @Jan (indirect) terecht op dat dit stuk DATA in je SQL ontdaan zou moeten worden van enige mogelijke speciale betekenis, zodat deze DATA niet als SQL geïnterpreteerd kan worden. Dan heb je namelijk te maken met een SQL-injectie met mogelijk ongewenste/catastrofale gevolgen.
Thomas en Jan, hartelijk dank. Het lukte makkelijker dan ik dacht.
Als ik jullie tips goed heb begrepen (en het werkt dus ik denk het wel) moest het dit worden:
<?php
$sqlc = "
UPDATE inloggen
SET land = '$ipland',
streek = '$ipstreek',
bezoekersoort = '$neemop',
eigenaar = '$ipeigenaar'
WHERE ipserver = '". mysqli_real_escape_string($link, $ip) ."'";
if(!$resc = mysqli_query($link, $sqlc))
{
echo "ip=".$ip."<br>";
trigger_error('Fout in query:'.mysqli_error());
mysqli_close($link);
}
?>
Alle DATA zou in principe ge-escaped moeten worden. Dit is de makkelijkste -en meest consequente- aanpak. Wanneer je alle DATA-delen (informatie van buitenaf) in je query onschadelijk maakt, bijvoorbeeld door het voorzien van quotes i.c.m. de juiste escape-functie dan is dat in principe veilig(er).
Dat is waarschijnlijk wat @Jan bedoelde: je escaped wel $ip, maar waarom niet ook $ipland, $ipstreek en $ipeigenaar? Zelfs als je de waarden van deze variabelen zelf definieert binnen je script is het uit oogpunt van "alle invoer hetzelfde behandelen" makkelijker om gewoon alles te escapen.
Prepared statements zijn een ander middel tot hetzelfde doel: veilige(re) queries. Het belangrijkste is dat je de gebruikte methodiek op de juiste manier (en daarmee dus ook consequent) toepast.
Een verkeerd gebruik van prepared statements is even onveilig, of wellicht onveiliger, omdat je dat in eerste instantie een vals gevoel van veiligheid kan geven.
Thomas en Jan, ik ben een beginner in PHP en MYSQL. Ik leer veel en ook nu steek ik een hoop van jullie antwoorden op.
Ik ben een groot voorstander van het KIS systeem. Ik begin heel basic en bouw het daarna op. Veiligheid komt dan wat later. Het bovenstaande is een eenmalig script om een berg data van mijn eigen server aan te passen op mijn eigen server. De opmerkingen van jullie ga ik zeker gebruiken in al bestaande scripts die de gebruikers statistieken invoeren.
En na weer heel veel dagen ploeteren, internet, boeken bekijken en uitproberen kom ik weer vast te zitten met hetzelfde probleem.
Ik heb 3 tabellen. 1)bezoekers 2)eigenaren en 3)inloggen.
In bezoekers zitten de IPadressen van bezoekers. In eigenaren zitten de land en streek codes van de IP adressen.
Nu wil ik de bezoekers van land en streek coden voorzien. De nieuwe bezoekers worden meteen voorzien bij het bezoek maar de al eerder genoteerde bezoekers hebben geen land en streek code. (Ik ben er achter gekomen dat Digital Ocean als eigenaar van veel IP reeks adressen vreemd vaak bezoekt.)
Dus ik open met sql1 bezoekers, kijk of land ingevuld is.
Open sql2 en vergelijk het ip adres met een reeks adres, is dat bekend dan gegevens aanvullen.
Open sql3 en voer de wel of niet aangevulde gegevens in bij inloggen.
Probleem is dat ik eerst veel fout meldingen krijg en daarna ineens werkt het script.
Is er een script fout dan moet het constant fout gaan.
Het script moet m.i. goed zijn maar waar komen de foutmeldingen dan door.
Zoals ik al eerder aangaf ik ben een beginner die door internet een hoop oppikt.
[size=xsmall][i]Toevoeging op 04/02/2018 10:18:56:[/i][/size]
<LINK REL=Stylsheet HREF="cybot.css" style type="text/css">
<BODY BACKGROUND="../images/perkament.jpg">
<?php
error_reporting(E_ALL);
// Report all PHP errors (see changelog)
// Zoek alle regels zonder land
echo "<table>";
echo "<tr><td>dag</td><td>datum</td><td>tijd</td><td>IPadres</td><td>pagina</td><td>bezoekersoort</td><td>land</td><td>streek</td><td>eigenaar</td><td>komt van</td></tr>";
include 'config.php';
$sqll = "SELECT * FROM bezoekers WHERE land=''";
if(!$res1 = mysqli_query($link, $sqll))
{
trigger_error('Fout in query: '.mysqli_error());
mysqli_close($link);
}else{
while($rij1 = mysqli_fetch_assoc($res1))
{
$bezoekersoort="0";
$dag=$rij1['dag'];
$datum=$rij1['datum'];
$tijd=$rij1['tijd'];
$ipserver=$rij1['ipserver'];
$ipvan=$rij1['ipvan'];
$pagina=$rij1['pagina'];
$komtvan=$rij1['komtvan'];
$bezoekersoort=$rij1['bezoekersoort'];
//------------vergelijk daarvan elke regel met de reeks uit eigenaren
$sql2 = "SELECT * FROM eigenaren";
if(!$res2 = mysqli_query($link, $sql2))
{
trigger_error('Fout in query: '.mysqli_error());
mysqli_close($link);
}else{
while($row = mysqli_fetch_assoc($res2))
{
$ipreeks = $row['ipreeks'];
$ipland = $row['ipland'];
$ipstreek = $row['ipstreek'];
$ipeigenaar = $row['ipeigenaar'];
$ipsoort = $row['ipsoort'];
$iplengte1 = strlen($ipserver);
$iplengte2 = strlen($ipreeks);
$iplengteverschil= ($iplengte1-$iplengte2);
$ipvergelijk=substr($ipserver,0,$iplengte2);
if ($ipvergelijk== $ipreeks)
{
$bezoekersoort=$ipsoort;
$land=$ipland;
$streek=$ipstreek;
$eigenaar=$ipeigenaar;
//---------------------data individuele IP
}// einde if vergelijk
}// einde while
}// einde sql2
// data is of wel of niet aangevuld
echo "<tr><td>".$dag."</td><td>".$datum."</td><td>".$tijd."</td><td>".$ipserver."</td><td>".$ipvan."</td><td>".$pagina."</td><td>".$bezoekersoort."</td><td>".$land."</td><td>".$streek."</td><td>".$eigenaar."</td><td>".$komtvan."</td></tr>";
$sql3 = "INSERT INTO inloggen(dag,datum,tijd,ipserver,ipvan,pagina,komtvan,bezoekersoort,land,streek,eigenaar)VALUES ('$dag','$datum','$tijd','$ipserver','$ipvan','$pagina','$komtvan','$bezoekersoort','$land','$streek','$eigenaar')";
if(!$res3 = mysqli_query($link, $sql3))
{
trigger_error('Fout in query: '.mysqli_error());
mysqli_close($link);
}//einde if sql3
}// einde While opzoeken van rege regels
}// einde sql1
echo "</table>";
mysqli_close($link);
?>
Ik zou het loggen van bezoek/IP's in ieder geval lostrekken van het uitzoeken in welk land/streek een IP thuishoort als hier al geen sprake van is.
En als het vastligt welk IP waar geografisch thuishoort als deze in een zeker interval zit (heb hier eigenlijk nooit een studie van gemaakt), maak hier dan gebruik van? In principe is een IP een getal (althans in IPv4) in het 256-tallige stelsel: aaa.bbb.ccc.ddd. Dit zou je dus om kunnen zetten naar een getal:
aaa * 256^3 +
bbb * 256^2 +
ccc * 256^1 +
ddd * 256^0
waarna je met een BETWEEN zou kunnen kijken in welk(e) interval(len) zo'n IP valt.