abstract class/login probleem
Er is een inlogscherm waar je kunt inloggen en als je je wachtwoord niet meer weet een nieuw wachtwoord aan kunt vragen, en er is een admin gedeelte dat controleert of de gebruiker rechten heeft om op de pagina te zijn, en waar de gebruiker zijn gegevens kan aanpassen.
Nu heb ik vanaf het begin af aan mijn hoofd zitten breken over de inlog pagina, omdat er zoveel opties zijn.
er kunnen een session variabelen zijn die gecontroleerd moeten worden (als er al ingelogd is) en er kunnen post variabelen zijn die gecontroleerd moeten worden (als er ingelogd word).
In beide gevallen kunnen zich dan de volgende situaties voordoen:
- email adres komt niet in db voor
- wachtwoord komt niet overeen met wachtwoord in db
- beide komen overeen en de gebruiker is ingelogd
Nu heb ik een abstract class LoginHandler gemaakt die het email adres en het wachtwoord controleert, waarbij de child classes voor post en session variabelen bepalen wat de uiteindelijke actie is die ondernomen moet worden.
Maar, als iemand zijn wachtwoord vergeten is en op de link 'wachtwoord vergeten' klikt, heb ik weer een deel van de functionaliteit van de LoginHandler class nodig. Voordat ik namelijk een nieuw wachtwoord aan kan maken en kan mailen, moet ik wel weten of het email adres in de database voorkomt. De functie daarvoor staat al in LoginHandler. Maar, in de child class zou ik dan maar 2 van de 4 abstract functions hoeven te gebruiken. Wat een foutmelding oplevert. Ik kan natuurlijk 2 lege functies in de child class zetten, maar deze hele situatie maakt dat ik me ernstig afvraag of ik het überhaupt niet helemaal verkeerd heb aangepakt.
Mijn vraag, lijkt dit ergens op en zo nee, hoe kan ik dit beter aanpakken?
De abstract class LoginHandler:
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
<?php
abstract class LoginHandler {
/**
* ingevoerde gebruikersnaam
*/
private $invoeremail;
/**
* ingevoerd wachtwoord
*/
private $invoerwachtwoord;
/**
* ingevoerde naam gebruiker
*/
private $db_handler;
/**
* prefix die gebruikt wordt voor unieke tabelnamen in database, uit settings
*/
private $prefix;
/**
* constructor die de inloggegevens verwerkt
*/
public function __construct( $prefix, DatabaseHandler $db_handler, $invoeremail, $invoerwachtwoord ){
$this->prefix = $prefix;
$this->db_handler = $db_handler;
$this->invoeremail = $invoeremail;
$this->invoerwachtwoord = $invoerwachtwoord;
}
/**
* controleer of het email adres voorkomt in de database
*/
public function check_login(){
$this->velden = array( "gebruikers_email", "gebruikers_ID" );
$this->db_handler->select_single ( $this->prefix . 'Gebruikers', $this->velden, 'gebruikers_email', $this->invoeremail );
$this->gebruikers_email = $this->db_handler->get_single( "gebruikers_email" );
$this->gebruikers_ID = $this->db_handler->get_single( "gebruikers_ID" );
if ( !empty( $this->gebruikers_email ) && !empty( $this->gebruikers_ID ) ){
//het email adres staat in de database, controleer nu het wachtwoord
return $this->email_match();
} else {
//het email adres staat niet in de database
return $this->geen_email_match();
}
}//end function check_email()
/**
* controleer of het wacthwoord overeenkomt met het ingevulde wachtwoord
*/
public function check_wachtwoord() {
$this->velden = array( "gebruikers_email", "gebruikers_ID", "gebruikers_wachtwoord" );
$this->db_handler->select_single ( $this->prefix . 'Gebruikers', $this->velden, 'gebruikers_email', $this->gebruikers_email );
$this->gebruikers_wachtwoord = $this->db_handler->get_single( "gebruikers_wachtwoord" );
$this->gebruikers_ID = $this->db_handler->get_single( "gebruikers_ID" );
if ( password_verify( $this->invoerwachtwoord, $this->gebruikers_wachtwoord )) {
//wachtwoorden komen overeen, stel de session variabelen in en redirect naar de juiste pagina
return $this->inlog_match();
} else {
//wachtwoorden komen niet overeen
return $this->geen_wachtwoord_match();
}
}//end function check_wachtwoord()
abstract function geen_email_match();
abstract function email_match();
abstract function inlog_match();
abstract function geen_wachtwoord_match();
}//end class Login_Handler
?>
abstract class LoginHandler {
/**
* ingevoerde gebruikersnaam
*/
private $invoeremail;
/**
* ingevoerd wachtwoord
*/
private $invoerwachtwoord;
/**
* ingevoerde naam gebruiker
*/
private $db_handler;
/**
* prefix die gebruikt wordt voor unieke tabelnamen in database, uit settings
*/
private $prefix;
/**
* constructor die de inloggegevens verwerkt
*/
public function __construct( $prefix, DatabaseHandler $db_handler, $invoeremail, $invoerwachtwoord ){
$this->prefix = $prefix;
$this->db_handler = $db_handler;
$this->invoeremail = $invoeremail;
$this->invoerwachtwoord = $invoerwachtwoord;
}
/**
* controleer of het email adres voorkomt in de database
*/
public function check_login(){
$this->velden = array( "gebruikers_email", "gebruikers_ID" );
$this->db_handler->select_single ( $this->prefix . 'Gebruikers', $this->velden, 'gebruikers_email', $this->invoeremail );
$this->gebruikers_email = $this->db_handler->get_single( "gebruikers_email" );
$this->gebruikers_ID = $this->db_handler->get_single( "gebruikers_ID" );
if ( !empty( $this->gebruikers_email ) && !empty( $this->gebruikers_ID ) ){
//het email adres staat in de database, controleer nu het wachtwoord
return $this->email_match();
} else {
//het email adres staat niet in de database
return $this->geen_email_match();
}
}//end function check_email()
/**
* controleer of het wacthwoord overeenkomt met het ingevulde wachtwoord
*/
public function check_wachtwoord() {
$this->velden = array( "gebruikers_email", "gebruikers_ID", "gebruikers_wachtwoord" );
$this->db_handler->select_single ( $this->prefix . 'Gebruikers', $this->velden, 'gebruikers_email', $this->gebruikers_email );
$this->gebruikers_wachtwoord = $this->db_handler->get_single( "gebruikers_wachtwoord" );
$this->gebruikers_ID = $this->db_handler->get_single( "gebruikers_ID" );
if ( password_verify( $this->invoerwachtwoord, $this->gebruikers_wachtwoord )) {
//wachtwoorden komen overeen, stel de session variabelen in en redirect naar de juiste pagina
return $this->inlog_match();
} else {
//wachtwoorden komen niet overeen
return $this->geen_wachtwoord_match();
}
}//end function check_wachtwoord()
abstract function geen_email_match();
abstract function email_match();
abstract function inlog_match();
abstract function geen_wachtwoord_match();
}//end class Login_Handler
?>
Child class LoginHandlerWachtwoord (bij vergeten wachtwoord)
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
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
<?php
/**
* child class de uitvoer van een verloren wachtwoord regelt
*/
class LoginHandlerWachtwoord extends LoginHandler {
/**
* als het email adres overeenkomt met dat in de database worden de gegevens opgeslagen en het wachtwoord hersteld
*/
public function email_match(){
$_SESSION[ 'vergetenwachtwoordid' ] = $this->gebruikers_ID;
$_SESSION[ 'vergetenwachtwoordemail' ] = $this->gebruikers_email;
$this->fout = 'wachtwoordherstellen.php';
return $this->fout;
}//end function email_match
/**
* als het email adres niet in de database voorkomt wordt het inlogscherm getoond met bijbehorende foutmelding
*/
public function geen_email_match(){
$this->fout = '../index.php?fout=1';
return $this->fout;
}//end function geen_email_match
private function inlog_match(){
//lege functie omdat ik hem niet gebruikt in deze situatie
}
private function geen_wachtwoord_match(){
//lege functie omdat ik hem niet gebruikt in deze situatie
}
}//end class LoginHandlerWacthwoord
?>
/**
* child class de uitvoer van een verloren wachtwoord regelt
*/
class LoginHandlerWachtwoord extends LoginHandler {
/**
* als het email adres overeenkomt met dat in de database worden de gegevens opgeslagen en het wachtwoord hersteld
*/
public function email_match(){
$_SESSION[ 'vergetenwachtwoordid' ] = $this->gebruikers_ID;
$_SESSION[ 'vergetenwachtwoordemail' ] = $this->gebruikers_email;
$this->fout = 'wachtwoordherstellen.php';
return $this->fout;
}//end function email_match
/**
* als het email adres niet in de database voorkomt wordt het inlogscherm getoond met bijbehorende foutmelding
*/
public function geen_email_match(){
$this->fout = '../index.php?fout=1';
return $this->fout;
}//end function geen_email_match
private function inlog_match(){
//lege functie omdat ik hem niet gebruikt in deze situatie
}
private function geen_wachtwoord_match(){
//lege functie omdat ik hem niet gebruikt in deze situatie
}
}//end class LoginHandlerWacthwoord
?>
Eerste vraag is daarom: waarom wil je de toestanden wel/geen geldig wachtwoord niet implementeren, maar de twee toestanden wel/geen geldig e-mailadres wel? Mis je dan niet de helft van een login?
Gewijzigd op 29/01/2017 17:26:50 door Ward van der Put
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
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
<?php
class LoginHandlerSession extends LoginHandler {
/*
* als het email adres overeenkomt met dat in de database wordt het wachtwoord gecheckt (parent functie)
*/
public function email_match(){
return $this->check_wachtwoord( $this->invoerwachtwoord );
}//end function email_match
/**
* als het email adres niet overeenkomt met dat in de database wordt het inlogscherm weer getoond met foutmelding
*/
public function geen_email_match(){
$this->fout = '../index.php?fout=3';
return $this->fout;
}//end function geen_email_match
/**
* als het wachtwoord niet overeenkomt met dat in de database wordt het inlogscherm weer getoond met foutmelding
*/
public function geen_wachtwoord_match(){
$this->fout = '../index.php?fout=3';
return $this->fout;
}//end function geen_wachtwoord_match
/**
* als het email adres en het wachtwoord kloppen krijgt de gebruiker toegang
*/
public function inlog_match(){
return 1;
}//end function geen_wachtwoord_match
}//end class LoginHandlerSession
?>
class LoginHandlerSession extends LoginHandler {
/*
* als het email adres overeenkomt met dat in de database wordt het wachtwoord gecheckt (parent functie)
*/
public function email_match(){
return $this->check_wachtwoord( $this->invoerwachtwoord );
}//end function email_match
/**
* als het email adres niet overeenkomt met dat in de database wordt het inlogscherm weer getoond met foutmelding
*/
public function geen_email_match(){
$this->fout = '../index.php?fout=3';
return $this->fout;
}//end function geen_email_match
/**
* als het wachtwoord niet overeenkomt met dat in de database wordt het inlogscherm weer getoond met foutmelding
*/
public function geen_wachtwoord_match(){
$this->fout = '../index.php?fout=3';
return $this->fout;
}//end function geen_wachtwoord_match
/**
* als het email adres en het wachtwoord kloppen krijgt de gebruiker toegang
*/
public function inlog_match(){
return 1;
}//end function geen_wachtwoord_match
}//end class LoginHandlerSession
?>
en class LoginHandlerPost, die de afhandeling regelt als er gepost is vanaf het login formulier:
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
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
<?php
class LoginHandlerPost extends LoginHandler {
/**
* als het email adres overeenkomt met dat in de database wordt het wachtwoord gecheckt (parent functie)
*/
public function email_match(){
return $this->check_wachtwoord( $this->invoerwachtwoord );
}//end function email_match
/**
* als het email adres niet in de database voorkomt wordt het inlogscherm weer getoond met foutmelding
*/
public function geen_email_match(){
$this->fout = '../index.php?fout=1';
return $this->fout;
}//end function geen_email_match
/**
* als het wachtwoord niet overeenkomt met dat in de database wordt het inlogscherm weer getoond met foutmelding
*/
public function geen_wachtwoord_match(){
$this->fout = '../index.php?fout=2';
return $this->fout;
}//end function geen_wachtwoord_match
/**
* als het email adres en het wachtwoord kloppen worden de sessie variabelen ingesteld en krijgt de gebruiker
* dmv het instellen van de 1; toegang tot de admin
*/
public function inlog_match(){
$_SESSION[ 'loginemail' ] = $this->gebruikers_email;
$_SESSION[ 'loginwachtwoord' ] = $this->invoerwachtwoord;
$_SESSION[ 'gebruikers_ID' ] = $this->gebruikers_ID;
return 1;
}//end function geen_wachtwoord_match
}//end class PostLoginHandler
?>
class LoginHandlerPost extends LoginHandler {
/**
* als het email adres overeenkomt met dat in de database wordt het wachtwoord gecheckt (parent functie)
*/
public function email_match(){
return $this->check_wachtwoord( $this->invoerwachtwoord );
}//end function email_match
/**
* als het email adres niet in de database voorkomt wordt het inlogscherm weer getoond met foutmelding
*/
public function geen_email_match(){
$this->fout = '../index.php?fout=1';
return $this->fout;
}//end function geen_email_match
/**
* als het wachtwoord niet overeenkomt met dat in de database wordt het inlogscherm weer getoond met foutmelding
*/
public function geen_wachtwoord_match(){
$this->fout = '../index.php?fout=2';
return $this->fout;
}//end function geen_wachtwoord_match
/**
* als het email adres en het wachtwoord kloppen worden de sessie variabelen ingesteld en krijgt de gebruiker
* dmv het instellen van de 1; toegang tot de admin
*/
public function inlog_match(){
$_SESSION[ 'loginemail' ] = $this->gebruikers_email;
$_SESSION[ 'loginwachtwoord' ] = $this->invoerwachtwoord;
$_SESSION[ 'gebruikers_ID' ] = $this->gebruikers_ID;
return 1;
}//end function geen_wachtwoord_match
}//end class PostLoginHandler
?>
Toevoeging op 29/01/2017 16:12:20:
Als de gebruiker zijn wachtwoord kwijt is, dan hoeft het wachtwoord dus niet gecontroleerd te worden, alleen het email adres, voordat ik een nieuw wachtwoord aanmaak en mail
Marlies Maalderink op 29/01/2017 16:11:16:
Als de gebruiker zijn wachtwoord kwijt is, dan hoeft het wachtwoord dus niet gecontroleerd te worden, alleen het email adres, voordat ik een nieuw wachtwoord aanmaak en mail
Klopt, dan is het geen login. En dus geen functionaliteit die een abstract class LoginHandler extendt, want er is geen login...
Je hebt dus een (abstract) class die te veel doet. Dat is een veelvoorkomend maar geen makkelijk probleem bij OOP programmeren.
Lang verhaal kort: je hebt die verificatie van een e-mailadres niet alleen nodig bij het inloggen maar ook bij een vergeten wachtwoord, dus je moet die refactoren naar iets dat op zich staat en wordt gebruikt door andere classes. De verificatie van een e-mailadres hoort niet thuis in de login zodra deze ook voor andere classes belangrijk is.
Het verifiëren van het email adres en van het wachtwoord zal dan dus naar twee losse classes moeten. Maar je kan een child class geen gebruik laten maken van 2 parents. Mag ik vragen hoe jij dit zou structureren?
Zoals ik het zie doen die handlers iets met pagina(navigatie), formulieren en superglobals. En tegelijkertijd ben je bezig met het authenticeren van een gebruiker. Ik zou een user class aanmaken. Met ten minste twee methoden: een die een gebruiker authenticeert (invoer: gebruikersnaam, wachtwoord, uitvoer: een user id of false of wat dan ook) en een die een gebruiker inlogt (invoer: een user id, uitvoer: een boolean of het inloggen is geslaagd). Vervolgens onthoud je een user id in de sessie en herbouw je elke page-access het user object. Binnen je applicatie refereer je alleen aan dit user object, en niet aan je sessie of wat dan ook.
Overigens las ik gisteren (ik geloof hier op het forum ergens maar misschien was het ook wel ergens anders) dat het sowieso niet zo slim is om bij het inloggen een aparte foutmelding weer te geven voor 'email adres komt niet voor' en voor 'wachtwoord klopt niet' dus dat maakt het aantal mogelijke uitvoer opties ook weer kleiner. Je hebt dan nog maar 2 opties. Inloggen is gelukt of inloggen is niet gelukt...