script werkt niet voor bruteforce
Maar in mijn vorige post (Niet de ene met procedurele code) maar object-georiënteerd, daar had ik dat toch al?
Uiteraard met proxies enz kun je dit weer onzeilen, iemand in israel kan een nederlandse proxy gebruiken
dab kun je wel HTTP_X_FORWARDED_FOR gebruiken welke ook nep kan zijn, dus kun je ze geheel blokkeren indien gewenst. dan heb je ook nog vpn connecties waar je weinig tegen kan doen.
@TS, ik zou niet vermelden welke landen toegestaan zijn ;)
Gewijzigd op 18/03/2017 16:34:30 door Dennis WhoCares
Toevoeging op 18/03/2017 16:35:25:
"@TS, ik zou niet vermelden welke landen toegestaan zijn ;)"
dan doe ik deze simpele fout: Er is een onbekende fout opgetreden.
hostnames en ipranges die je vaak zal moeten bijwerken enz, let er wel op :)
ipinfo.io werkt hun database heel vaak bij.
Ik laat eens wat van mijn code zien. Het is niet alles, en de class is ook even gestript van het onnodige, en het is ook niet super OO-gebouwd (ik ben er ook geen extreme kei in), maar voor mij doet het wat het moet doen, en het is naar mijn idee ook logisch opgebouwd.
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
require("/classes/news.class.php");
$slug = new Slug();
$news = new News($db,$settings); // deze worden al eerder opgehaald via een include buiten dit stukje script. $db is een extend op de interne MySQLi class. Deze kent nog wat extra functies, zoals queries tellen en foutafhandeling.
if (empty($param[0])) { // kijk in de URL of er een ID-nummer is.
throw new Exception('news_no_value');
} else {
$data = $news->getNewsByID($param[1]);
if(!isset($param[2])) {
header("HTTP/1.1 301 Moved Permanently");
header('location:http://'.$_SERVER['HTTP_HOST']."/news/".$param[1]."/".$slug->create($data['title']));
exit();
}
$tpl->assign("title",htmlentities($data['title'], ENT_COMPAT,'ISO-8859-1', true));
$tpl->assign("data",$data);
$tpl->assign("tags",$data['tags']);
$tpl->display("news.tpl");
//$tpl is de instance van Smarty, de template-class waarmee ik PHP en HTML strict gescheiden houd. Als ik het opnieuw zou doen zou ik Twig gebruiken of de plain functies van PHP zelf.
}
?>
require("/classes/news.class.php");
$slug = new Slug();
$news = new News($db,$settings); // deze worden al eerder opgehaald via een include buiten dit stukje script. $db is een extend op de interne MySQLi class. Deze kent nog wat extra functies, zoals queries tellen en foutafhandeling.
if (empty($param[0])) { // kijk in de URL of er een ID-nummer is.
throw new Exception('news_no_value');
} else {
$data = $news->getNewsByID($param[1]);
if(!isset($param[2])) {
header("HTTP/1.1 301 Moved Permanently");
header('location:http://'.$_SERVER['HTTP_HOST']."/news/".$param[1]."/".$slug->create($data['title']));
exit();
}
$tpl->assign("title",htmlentities($data['title'], ENT_COMPAT,'ISO-8859-1', true));
$tpl->assign("data",$data);
$tpl->assign("tags",$data['tags']);
$tpl->display("news.tpl");
//$tpl is de instance van Smarty, de template-class waarmee ik PHP en HTML strict gescheiden houd. Als ik het opnieuw zou doen zou ik Twig gebruiken of de plain functies van PHP zelf.
}
?>
En de class:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
class News {
public $db;
private $settings;
public function __construct($db,$settings) {
$this->db = $db;
$this->settings = $settings;
}
public function getNewsByID($id) {
$sql = "SELECT een,hoop,velden FROM nieuwstabel WHERE '".$this->db->escape_string($id)."'"; // fictieve querie, niet relevant voor voorbeeld.
$result = $this->db->query($sql);
if($result->num_rows==0) {
header("HTTP/1.0 404 Not Found");
throw new Exception('news_not_found'); // in de exceptionhandler vindt een vertaalslag plaats naar een goed leesbare foutmelding die iedereen snapt.
}
return $result->fetch_assoc();
}
?>
class News {
public $db;
private $settings;
public function __construct($db,$settings) {
$this->db = $db;
$this->settings = $settings;
}
public function getNewsByID($id) {
$sql = "SELECT een,hoop,velden FROM nieuwstabel WHERE '".$this->db->escape_string($id)."'"; // fictieve querie, niet relevant voor voorbeeld.
$result = $this->db->query($sql);
if($result->num_rows==0) {
header("HTTP/1.0 404 Not Found");
throw new Exception('news_not_found'); // in de exceptionhandler vindt een vertaalslag plaats naar een goed leesbare foutmelding die iedereen snapt.
}
return $result->fetch_assoc();
}
?>
Nogmaals, het is niet 100% optimaal, en er zullen vast mensen zijn die kritische puntjes hebben.
Uiteraard sta ik daar voor open (houd wel ruimte voor de vraag van de TS), hoewel de beslissing om een framework te gebruiken er nog steeds ligt voor ooit! Niet nu, tenzij ik weer met deadlines moet gaan schuiven en weer ene hoop ervaring met frameworks op moet doen. ;-)
Niets is 100% perfect, hoewel dit al wel veel beter is dan de procedurele rotzooi is die ik voorheen had.
Gewijzigd op 18/03/2017 16:51:30 door - Ariën -
Maar waar had ik dan mysqli_query() in mijn eerste code?
Code (php)
1
2
3
2
3
<?php
searchUserSql = mysqli_query($mysqli, "SELECT `id`, `wachtwoord` FROM `leden` WHERE `gebruikersnaam`='".mysqli_real_escape_string($username)."'");
?>
searchUserSql = mysqli_query($mysqli, "SELECT `id`, `wachtwoord` FROM `leden` WHERE `gebruikersnaam`='".mysqli_real_escape_string($username)."'");
?>
Tenzij je het al aangepast hebt.
Toevoeging op 18/03/2017 17:25:00:
Ik heb een nieuwe public functie aangemaakt, om te registreren en ik plaats hem even om te kijken of ik het allemaal goed doe ;D
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<?php
public function register($username, $password, $password_repeat, $email)
{
$mysqli = $this->_mysqli;
$ip = $_SERVER['REMOTE_ADDR'];
$ipInfo = json_decode(file_get_contents("http://ipinfo.io/$ip/json"));
$country = $ipInfo->country;
if ($country === "NL" || $country === "BE")
{
$searchUserSql = $mysqli->query("SELECT * FROM `leden` WHERE `gebruikersnaam`='".$mysqli->real_escape_string($username)."'");
$searchEmailSql = $mysqli->query("SELECT * FROM `leden` WHERE `emailadres`='".$mysqli->real_escape_string($email)."'");
if (
$searchUserSql
&& $searchEmailSql
&& isset($searchUserSql->num_rows)
&& isset($searchEmailSql->num_rows)
)
{
if (
strlen($username) >= 2
&& strlen($username) <= 15
&& $password === $password_repeat
&& preg_match("/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[$%^&!@#$*()]).*$/", $password)
&& strlen($password) >= 8
&& !filter_var($emailadres, FILTER_VALIDATE_EMAIL)
)
{
$insertUserSql = $mysqli->query("INSERT INTO `leden` (`gebruikersnaam`, `wachtwoord`, `emailadres`, `ip`, `registratie_datum`) VALUES ('".$mysqli->real_escape_string($username)."', '".$mysqli->real_escape_string(password_hash($password, PASSWORD_DEFAULT))."', '".$mysqli->real_escape_string($email)."', '".sha1($ip)."', '".time()."')");
if (!$insertUserSql)
{
echo '0+Er is een onbekende fout opgetreden.';
}
else
{
echo '1+Je account is aangemaakt, je kan nu inloggen.';
}
}
else
{
echo '0+De ingevulde gegevens zijn niet goed2.';
}
}
else
{
echo '0+De ingevulde gegevens zijn niet goed1.';
}
}
else
{
echo '0+Er is een onbekende fout opgetreden.';
}
?>
public function register($username, $password, $password_repeat, $email)
{
$mysqli = $this->_mysqli;
$ip = $_SERVER['REMOTE_ADDR'];
$ipInfo = json_decode(file_get_contents("http://ipinfo.io/$ip/json"));
$country = $ipInfo->country;
if ($country === "NL" || $country === "BE")
{
$searchUserSql = $mysqli->query("SELECT * FROM `leden` WHERE `gebruikersnaam`='".$mysqli->real_escape_string($username)."'");
$searchEmailSql = $mysqli->query("SELECT * FROM `leden` WHERE `emailadres`='".$mysqli->real_escape_string($email)."'");
if (
$searchUserSql
&& $searchEmailSql
&& isset($searchUserSql->num_rows)
&& isset($searchEmailSql->num_rows)
)
{
if (
strlen($username) >= 2
&& strlen($username) <= 15
&& $password === $password_repeat
&& preg_match("/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[$%^&!@#$*()]).*$/", $password)
&& strlen($password) >= 8
&& !filter_var($emailadres, FILTER_VALIDATE_EMAIL)
)
{
$insertUserSql = $mysqli->query("INSERT INTO `leden` (`gebruikersnaam`, `wachtwoord`, `emailadres`, `ip`, `registratie_datum`) VALUES ('".$mysqli->real_escape_string($username)."', '".$mysqli->real_escape_string(password_hash($password, PASSWORD_DEFAULT))."', '".$mysqli->real_escape_string($email)."', '".sha1($ip)."', '".time()."')");
if (!$insertUserSql)
{
echo '0+Er is een onbekende fout opgetreden.';
}
else
{
echo '1+Je account is aangemaakt, je kan nu inloggen.';
}
}
else
{
echo '0+De ingevulde gegevens zijn niet goed2.';
}
}
else
{
echo '0+De ingevulde gegevens zijn niet goed1.';
}
}
else
{
echo '0+Er is een onbekende fout opgetreden.';
}
?>
Ook de foutafhandeling kan je extraheren naar de extended MySQLi-class, en daar de query() method klonen, en foutafhandeling erin bouwen. Mogelijk dat dit beter kan, maar zo doe ik het. Het scheelt in elke method weer een extra if-else controle bij de query.
Verder horen er geen echo's in een class.... Dus laat een functie-aanroep uitsluitend iets van true of false of een integer afgeven via return.
Gewijzigd op 18/03/2017 17:45:39 door - Ariën -
Dan zal ik die echo wel even aanpassen ;-)
Die validatie kan je omzetten in een array met validatiefouten, welke je returned vanuit de Validatie-class.
overigens zou je als eerste je validatie moeten uitvoeren en dan pas verwerken
Dat klopt. Je kan een object aanmaken met getValidationErrors(). Als deze leeg is (of 0) is er aan de controles voldaan, en kan je de verwerking starten.
Waarom ga je niet eerst de basis wat beter leren? Een tijdje terug is je al verteld dat je code een zootje is, en vervolgens zie ik nu weer dat je op precies dezelfde manier bezig bent. Je wil teveel en je neemt te weinig aan van mensen die jou tips geven, zoals hierboven bijv. de tips van Ariën.
Als je nog niet weet hoe bepaalde zaken werken, dan is het zinvol om daar eerst je tijd en energie in te steken, en om daarmee te gaan oefenen. Hoe je nu bezig bent BLIJF je tegen allerlei problemen aanlopen.
Zorg ervoor dat je per regel in je hoofd kan vertellen wat er exact gebeurt.
Maak je code leesbaar! Nu snap je misschien wat je aan het doen bent, maar over twee weken is er voor jezelf ook geen touw meer aan vast te knopen. Al die ifs en elses is (met alle respect) totale bagger. Niemand ziet wat je aan het doen bent en de code is totaal niet te onderhouden. Code moet je in één oogopslag kunnen lezen als een boek. Dat is bij jou absoluut niet het geval. Dat van jou lijkt meer op een kruiswoordpuzzel. En een functie moet kort zijn. Die van jou is een lange onleesbare brij. Begin bij het begin. Zorg dat je de basis begrijpt. Ga eerst kleine dingen maken ter oefening. Dit is de laatste keer dat ik het nu zeg. Doe ermee wat je wilt.