Simpel login script zonder database
Mijn vraag is dan ook wat kan ik verbeteren aan dit simpel script.
In het dashboard staat geen gevoelige informatie en je kan echter alleen dingen lezen en niks aanpassen.
Login.php
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
$error = '';
if(isset($_POST['username'], $_POST['password'])){
$username = $_POST['username'];
$password = hash('sha512', $_POST['password']);
if($username !== 'admin' ){
$error = 0;
}
if($password !== 'C7AD44CBAD762A5DA0A452F9E854FDC1E0E7A52A38015F23F3EAB1D80B931DD472634DFAC71CD34EBC35D16AB7FB8A90C81F975113D6C7538DC69DD8DE9077EC' ){
$error = 0;
}
if($error !== 0)
session_start();
$_SESSION['valid'] = true;
$_SESSION['username'] = 'Administrator';
header('Refresh: 0; URL = dashboard.php');
}
}
?>
$error = '';
if(isset($_POST['username'], $_POST['password'])){
$username = $_POST['username'];
$password = hash('sha512', $_POST['password']);
if($username !== 'admin' ){
$error = 0;
}
if($password !== 'C7AD44CBAD762A5DA0A452F9E854FDC1E0E7A52A38015F23F3EAB1D80B931DD472634DFAC71CD34EBC35D16AB7FB8A90C81F975113D6C7538DC69DD8DE9077EC' ){
$error = 0;
}
if($error !== 0)
session_start();
$_SESSION['valid'] = true;
$_SESSION['username'] = 'Administrator';
header('Refresh: 0; URL = dashboard.php');
}
}
?>
dashboard.php
Code (php)
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
<?php
session_start();
if (isset($_SESSION['valid']) && $_SESSION['valid'] == true) {
}else{
header('Refresh: 0; URL = login.php');
}
?>
session_start();
if (isset($_SESSION['valid']) && $_SESSION['valid'] == true) {
}else{
header('Refresh: 0; URL = login.php');
}
?>
Gewijzigd op 08/05/2020 00:51:51 door Stefan Janssen
- Waarom is de username in de sessie hardcoded Administrator?
- Vergeet geen exit; na je header.
Het zijn in totaal maar 2 gebruikers die erop komen dus uitgebreid hoeft het niet ;-)
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php
$error = '';
if(isset($_POST['username'], $_POST['password'])){
$username = $_POST['username'];
$password = hash('sha512', $_POST['password']);
if($username !== 'admin' ){
$error = 0;
}
if($password !== 'C7AD44CBAD762A5DA0A452F9E854FDC1E0E7A52A38015F23F3EAB1D80B931DD472634DFAC71CD34EBC35D16AB7FB8A90C81F975113D6C7538DC69DD8DE9077EC' ){
$error = 0;
}
if($error !== 0)
session_start();
$_SESSION['valid'] = true;
//gebruikersnaam uit variabel en gelijk aan inlognaam veranderd
$_SESSION['username'] = $username;
header('Refresh: 0; URL = dashboard.php');
//exit toegevoegd
exit();
}
}
?>
$error = '';
if(isset($_POST['username'], $_POST['password'])){
$username = $_POST['username'];
$password = hash('sha512', $_POST['password']);
if($username !== 'admin' ){
$error = 0;
}
if($password !== 'C7AD44CBAD762A5DA0A452F9E854FDC1E0E7A52A38015F23F3EAB1D80B931DD472634DFAC71CD34EBC35D16AB7FB8A90C81F975113D6C7538DC69DD8DE9077EC' ){
$error = 0;
}
if($error !== 0)
session_start();
$_SESSION['valid'] = true;
//gebruikersnaam uit variabel en gelijk aan inlognaam veranderd
$_SESSION['username'] = $username;
header('Refresh: 0; URL = dashboard.php');
//exit toegevoegd
exit();
}
}
?>
Gewijzigd op 08/05/2020 01:03:26 door Stefan Janssen
Ik tel toch echt maar één gebruiker.
Ze loggen met de zelfde gegevens in, in het dashboard kun je zelf niets aanpassen alleen maar inzien :)
En wat als deelnemer twee nou opeens niet meer actief is voor de organisatie? Waarom geef je beiden geen eigen inlog?
Gewijzigd op 08/05/2020 01:19:09 door - Ariën -
Waarom werk je met $error = '' en $error = 0? Gebruik een omschrijvende naam en/of gebruik iig een Boolse waarde (true of false), dan hoef je ook niet met !== 0 te stunten, wat zonder die typecheck ook nogal gevaarlijk is want 0 en '' zijn equivalent als je simpelweg met == (of !=) vergelijkt, op die manier is een fout heel snel gemaakt, bij een Boolean is de kans op dit soort fouten min of meer afwezig...
Ook wil je misschien niet controleren of iets fout gaat, maar of iets goed gaat.
Dan zou je dus kunnen beginnen met $loginOk = false; en alleen als de gebruikersnaam bestaat en de wachtwoorden overeenkomen zet je $loginOk op true. Dit lijkt mij een stuk logischer dan er vanuit gaan dat de login goed is, en alleen als er dingen niet kloppen vervolgens toch maar concluderen dat de login niet goed was, wat je nu in feite doet; dit lijkt mij de omgekeerde wereld, en wederom heel erg gevaarlijk.
Tevens heeft je sessie geen enkele extra controles, bijvoorbeeld whitelisting van IP's of wat dan ook, dus als er ook maar iets in de rest van de code misgaat of iemand op enigerlei wijze je sessie-id kan ontvreemden dan kunnen zij je sessie overnemen en zijn ze binnen?
Duidelijk verhaal en ga ermee aan de slag :-)
@thomas,
Een check op de session zoals je aangeeft bijvoorbeeld door een ip check bedoel je daarmee zoiets
Zo voorkom je dat je sessie hetzelfde blijft en opeens overgenomen kan worden. De 'session fixation exploit'
Blijkbaar is een user agent "redelijk" uniek. Hoe dan ook, je zult op een of andere manier de identificatie van de machine moeten verankeren in je veiligheidschecks. Indien dit kenmerk op een of andere manier verandert tijdens gebruik zou je iemand direct moeten uitloggen omdat je in zekere zin de ingelogde gebruiker niet meer goed kunt identificeren, je weet simpelweg niet langer zeker of je met dezelfde persoon van doen hebt.
Ook wat @Ariën zegt en wellicht is een aanpak met password_hash() en password_verify() ook handig, als je dit ooit nog eens om wil schrijven naar een uitgebreider loginsysteem inclusief database.
Op het moment dat je met authenticatie / het afschermen van pagina's aan de slag gaat is het eigenlijk ook hoog tijd om over de opbouw van de rest van je applicatie na te denken. Dit om er zorg voor te dragen dat deze veilig is en blijft. Als je dus tig losse PHP-bestanden hebt heb je ook tig ingangen in jouw applicatie. De vraag is of dat een goed idee is, of dat je je beter kunt bedienen van een single point of entry.
De vraag is dan ook eigenlijk: waarom een simpel loginscript? Is dit vanwege tijdsdruk, of dat je echt gewoon een simpele backend nodig hebt? Dit is namelijk niet iets waar je zomaar op zou moeten beknibbelen; als je hier bewust bochten aan het afsnijden bent om tijd te besparen krijg je dit later, wanneer je niet goed hebt nagedacht over de architectuur, gewoon keihard terug op je bord. En dan is er al een complete applicatie opgebouwd, dan zou je dus de spreekwoordelijke grondvesten moeten aanpassen terwijl je huis al staat en zul je zorg moeten dragen voor het niet instorten ervan tijdens de renovatie. Je kunt beter van start gaan met een goed plan, in plaats van terloops allerlei innovaties/verbouwingen uit te voeren.
Maar misschien moet je hier gewoon een keer tegenaan lopen :p.
https://www.htaccessredirect.net/ Via de hostingzijde van een site is dit gemakkelijk in te stellen. Voor als je het echt simpel wilt.
Heb jij al een overwogen om een directory met .htaccess en .htpassword af te schermen, helemaal geen gedoe? En gemakkelijk. Er zijn zelfs generatoren voor. 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
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
<?php
//zoiets ongeveer ;-), code nog niet getest
//start de sessie
session_start();
//maak een array accounts met gebruikersnaam en wachtwoord
//Zorg dat je wachtwoorden een hash hebben en niet open bloot te lezen zijn.
$accounts = array(
'admin' => 'C7AD44CBAD762A5DA0A452F9E854FDC1E0E7A52A38015F23F3EAB1D80B931DD472634DFAC71CD34EBC35D16AB7FB8A90C81F975113D6C7538DC69DD8DE845TR',
'stefan' => 'C7AD44CBAD762A5DA0A452F9E854FDC1E0E7A52A38015F23F3EAB1D80B931DD472634DFAC71CD34EBC35D16AB7FB8A90C81F975113D6C7538DC69DD8DE9077EC',
);
//loop door de accounts van de array
foreach($accounts as $user => $password) {
//controleer op bestaan gebruikersnaam
if($name == $_POST["username"]{
//controleer het wachtwoord
if(password_verify($_POST['password'], $password)){
//sla gebruikersnaam op welke je kan gebruiken in het beveiligde gedeelte
$_SESSION['name'] = $_POST["username"];
session_regenerate_id();
//onderstaande kun je enkele checks uitvoeren, zoals het id controleren en IP adres controleren
$_SESSION['loggedin'] = TRUE;
$_SESSION['id'] = $id;
//sla het IP adres van de gebruiker op in een sessie variabel
$_SESSION['ip'] = $_SERVER['REMOTE_ADDR'];
//doe hier wat je wilt als iemand is ingelogd.
}else{
echo 'wachtwoord onjuist';
}
}else{
echo 'Gebruikersnaam onbekend';
}
}
?>
//zoiets ongeveer ;-), code nog niet getest
//start de sessie
session_start();
//maak een array accounts met gebruikersnaam en wachtwoord
//Zorg dat je wachtwoorden een hash hebben en niet open bloot te lezen zijn.
$accounts = array(
'admin' => 'C7AD44CBAD762A5DA0A452F9E854FDC1E0E7A52A38015F23F3EAB1D80B931DD472634DFAC71CD34EBC35D16AB7FB8A90C81F975113D6C7538DC69DD8DE845TR',
'stefan' => 'C7AD44CBAD762A5DA0A452F9E854FDC1E0E7A52A38015F23F3EAB1D80B931DD472634DFAC71CD34EBC35D16AB7FB8A90C81F975113D6C7538DC69DD8DE9077EC',
);
//loop door de accounts van de array
foreach($accounts as $user => $password) {
//controleer op bestaan gebruikersnaam
if($name == $_POST["username"]{
//controleer het wachtwoord
if(password_verify($_POST['password'], $password)){
//sla gebruikersnaam op welke je kan gebruiken in het beveiligde gedeelte
$_SESSION['name'] = $_POST["username"];
session_regenerate_id();
//onderstaande kun je enkele checks uitvoeren, zoals het id controleren en IP adres controleren
$_SESSION['loggedin'] = TRUE;
$_SESSION['id'] = $id;
//sla het IP adres van de gebruiker op in een sessie variabel
$_SESSION['ip'] = $_SERVER['REMOTE_ADDR'];
//doe hier wat je wilt als iemand is ingelogd.
}else{
echo 'wachtwoord onjuist';
}
}else{
echo 'Gebruikersnaam onbekend';
}
}
?>
Gewijzigd op 10/05/2020 14:59:10 door Jop B
Daarbij zou je ook geen enkele informatie moeten verschaffen over wat er fout is, anders kan een aanvaller gericht gaan vissen totdat 'ie een username heeft en vervolgens kan 'ie met je wachtwoord aan de slag...
$_SESSION['loggedin'] dient geen enkel doel.
$_SESSION['id'] bestaat niet.
Nog een dingetje wat betreft een IP check:
Stel dat iemand op zn telefoon doet inloggen en die telefoon is verbonden met de wifi dan word dat IP adres geregistreerd.
Maar als je dan buiten het wifi gebied raakt en over gaat op 4G dan veranderd het IPadres en zal je dus opnieuw moeten inloggen.
Dan is een IP check natuurlijk niet handig maar vervelend toch?
Ik heb ooit in het verleden een inlogsysteem gemaakt welke de inlogsessies opsloeg in de database, en aan de hand van een cookie jou identificeerde. Een voordeel daarvan was dat je zelf controle hebt over je inlogsessie. Zo kan je thuis bijvoorbeeld de inlogsessie die je op school gemaakt hebt weer uitloggen. Of gewoon op alle plekken waar je ingelogd bent.
Een van die functies was een IP-lock waarbij een sessie in de database alleen gekoppeld kon worden als het IP-adres klopt. Dit was bij het inloggen wel een keuze.
Ik denk dat het wel handig is om alle inlogacties en utigevoerde acties in je beveiligide omgeving gelogd worden. Zo kan je altijd zien wie met welk IP-adres bijvoorbeeld een nieuwsbericht heeft gewijzigd, en welke dat is. En eventueel zelfs wát er gewijzigd is. ('diff' in Linux).
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
session_start();
if($_SERVER['REQUEST_METHOD'] == 'POST'){
$account = array (
'stefan' => '$2y$10$96Yi1ezzoS6xZYjPhbvYTeCha.YypKF.7MSYwfruXtKaFyeGRLeMK',
'bert' => '$3g$10$96Yi1ezzoS6xZYjPhbvYTeCha.YypKF.7MSYwfruXtKaFyeGRLeMK',
);
if(array_key_exists($_POST['user'], $account)){
if(password_verify($_POST['password'], $account[$_POST['user']])){
session_regenerate_id();
$_SESSION['username'] = $_POST["user"];
$_SESSION["loggedin"]) = true;
header("location: protected_page.php");
}else{
echo 'Something wrong';
}
}else{
echo 'Something wrong';
}
}
?>
session_start();
if($_SERVER['REQUEST_METHOD'] == 'POST'){
$account = array (
'stefan' => '$2y$10$96Yi1ezzoS6xZYjPhbvYTeCha.YypKF.7MSYwfruXtKaFyeGRLeMK',
'bert' => '$3g$10$96Yi1ezzoS6xZYjPhbvYTeCha.YypKF.7MSYwfruXtKaFyeGRLeMK',
);
if(array_key_exists($_POST['user'], $account)){
if(password_verify($_POST['password'], $account[$_POST['user']])){
session_regenerate_id();
$_SESSION['username'] = $_POST["user"];
$_SESSION["loggedin"]) = true;
header("location: protected_page.php");
}else{
echo 'Something wrong';
}
}else{
echo 'Something wrong';
}
}
?>
Code (php)
Of zijn er nog dingen waar ik rekening mee moet houden?
Wat als een niet-technicus deze met spoed moet wijzigen omdat het password op straat ligt, en de IT'er op Ibiza ligt te zonnen?
Als het een aantal personen waren geweest had ik dit zeker gedaan maar voor 2 á 3 personen vind ik dit onzin om te doen.
Tot nu toe heb ik nog geen sterk argument gezien en lijkt het alsof je mijn bericht maar half gelezen hebt.
Gewijzigd op 11/05/2020 23:27:43 door - Ariën -
verandert in
(of iets equivalents)
en $_SESSION['loggedin'] gewoont schrapt?
Stel dat om een of andere reden de configuratie van de server zou veranderen en je php files niet als php geshowd worden maar als platte text dan zijn je gebruikers en je gehashte wachtwoorden in te zien omdat deze in de public map staan.
Als je je gebruikers en wachtwoorden hierbuiten neerzet dan is het weer een stukje veiliger.