inlog probleempje
Hier onder het inlog script.
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
<?php
/**
* Class login
* handles the user's login and logout process
*/
class Login
{
/**
* @var object The database connection
*/
private $db_connection = null;
/**
* @var array Collection of error messages
*/
public $errors = array();
/**
* @var array Collection of success / neutral messages
*/
public $messages = array();
/**
* the function "__construct()" automatically starts whenever an object of this class is created,
* you know, when you do "$login = new Login();"
*/
public function __construct()
{
// create/read session, absolutely necessary
session_start();
// check the possible login actions:
// if user tried to log out (happen when user clicks logout button)
if (isset($_GET["logout"])) {
$this->doLogout();
}
// login via post data (if user just submitted a login form)
elseif (isset($_POST["login"])) {
$this->dologinWithPostData();
}
}
/**
* log in with post data
*/
private function dologinWithPostData()
{
// check login form contents
if (empty ($_POST['user_name'])) {
$this->errors[] = "Gebruikernaam is leeg.";
} elseif (empty($_POST['user_password'])) {
$this->errors[] = "Wachtwoord is leeg.";
} elseif (!empty($_POST['user_name']) && !empty($_POST['user_password'])) {
// create a database connection, using the constants from config/db.php (which we loaded in index.php)
$this->db_connection = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME);
// change character set to utf8 and check it
if (!$this->db_connection->set_charset("utf8")) {
$this->errors[] = $this->db_connection->error;
}
// if no connection errors (= working database connection)
if (!$this->db_connection->connect_errno) {
// escape the POST stuff
$user_name = $this->db_connection->real_escape_string($_POST['user_name']);
// database query, getting all the info of the selected user (allows login via email address in the
// username field)
$sql = "SELECT user_name, user_email, user_password_hash
FROM users
WHERE user_name = '" . $user_name . "' OR user_email = '" . $user_name . "';";
$result_of_login_check = $this->db_connection->query($sql);
// if this user exists
if ($result_of_login_check->num_rows == 1) {
// get result row (as an object)
$result_row = $result_of_login_check->fetch_object();
// using PHP 5.5's password_verify() function to check if the provided password fits
// the hash of that user's password
if (password_verify($_POST['user_password'], $result_row->user_password_hash)) {
// write user data into PHP SESSION (a file on your server)
$_SESSION['user_name'] = $result_row->user_name;
$_SESSION['user_email'] = $result_row->user_email;
$_SESSION['user_login_status'] = 1;
} else {
$this->errors[] = "Fout wachtwoord. probeer het opnieuw.";
}
} else {
$this->errors[] = "Deze gebruikernaam bestaat niet.";
}
} else {
$this->errors[] = "Database connectie heeft een probleem.";
}
}
}
/**
* perform the logout
*/
public function doLogout()
{
// delete the session of the user
$_SESSION = array();
session_destroy();
// return a little feeedback message
$this->messages[] = "Je bent uitgelogt.";
}
/**
* simply return the current state of the user's login
* @return boolean user's login status
*/
public function isUserLoggedIn()
{
if (isset($_SESSION['user_login_status']) AND $_SESSION['user_login_status'] == 1) {
return true;
}
// default return
return false;
}
}
?>
/**
* Class login
* handles the user's login and logout process
*/
class Login
{
/**
* @var object The database connection
*/
private $db_connection = null;
/**
* @var array Collection of error messages
*/
public $errors = array();
/**
* @var array Collection of success / neutral messages
*/
public $messages = array();
/**
* the function "__construct()" automatically starts whenever an object of this class is created,
* you know, when you do "$login = new Login();"
*/
public function __construct()
{
// create/read session, absolutely necessary
session_start();
// check the possible login actions:
// if user tried to log out (happen when user clicks logout button)
if (isset($_GET["logout"])) {
$this->doLogout();
}
// login via post data (if user just submitted a login form)
elseif (isset($_POST["login"])) {
$this->dologinWithPostData();
}
}
/**
* log in with post data
*/
private function dologinWithPostData()
{
// check login form contents
if (empty ($_POST['user_name'])) {
$this->errors[] = "Gebruikernaam is leeg.";
} elseif (empty($_POST['user_password'])) {
$this->errors[] = "Wachtwoord is leeg.";
} elseif (!empty($_POST['user_name']) && !empty($_POST['user_password'])) {
// create a database connection, using the constants from config/db.php (which we loaded in index.php)
$this->db_connection = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME);
// change character set to utf8 and check it
if (!$this->db_connection->set_charset("utf8")) {
$this->errors[] = $this->db_connection->error;
}
// if no connection errors (= working database connection)
if (!$this->db_connection->connect_errno) {
// escape the POST stuff
$user_name = $this->db_connection->real_escape_string($_POST['user_name']);
// database query, getting all the info of the selected user (allows login via email address in the
// username field)
$sql = "SELECT user_name, user_email, user_password_hash
FROM users
WHERE user_name = '" . $user_name . "' OR user_email = '" . $user_name . "';";
$result_of_login_check = $this->db_connection->query($sql);
// if this user exists
if ($result_of_login_check->num_rows == 1) {
// get result row (as an object)
$result_row = $result_of_login_check->fetch_object();
// using PHP 5.5's password_verify() function to check if the provided password fits
// the hash of that user's password
if (password_verify($_POST['user_password'], $result_row->user_password_hash)) {
// write user data into PHP SESSION (a file on your server)
$_SESSION['user_name'] = $result_row->user_name;
$_SESSION['user_email'] = $result_row->user_email;
$_SESSION['user_login_status'] = 1;
} else {
$this->errors[] = "Fout wachtwoord. probeer het opnieuw.";
}
} else {
$this->errors[] = "Deze gebruikernaam bestaat niet.";
}
} else {
$this->errors[] = "Database connectie heeft een probleem.";
}
}
}
/**
* perform the logout
*/
public function doLogout()
{
// delete the session of the user
$_SESSION = array();
session_destroy();
// return a little feeedback message
$this->messages[] = "Je bent uitgelogt.";
}
/**
* simply return the current state of the user's login
* @return boolean user's login status
*/
public function isUserLoggedIn()
{
if (isset($_SESSION['user_login_status']) AND $_SESSION['user_login_status'] == 1) {
return true;
}
// default return
return false;
}
}
?>
wat us het create commando?
Niek Kasius op 24/01/2015 04:54:29:
namelijk dat in de database mijn naam met een hoofdletter staat, maar dat ik kan inloggen zonder hoofdletter.
Ik zou dat niet als probleem zien.
Zoals jij het wilt kun je dus straks voor jouw naam heel veel inlognamen krijgen:
Niek Kasius
NIek KaSius
niEk KASius
niek kasiuS
NIEk KaSiUS
etc.
Wat is er op tegen om een inlognaam uniek te houden?
Niek
niek
NieK
etc
Text-vergelijkingen (met A LIKE B, A = B etc.) van niet-binaire string-typen (CHAR, VARCHAR, TEXT) zijn case-insensitive. Zie mysql.com.
Wat je kunt doen om text-vergelijkingen case-sensitive te maken is:
- ofwel de betreffende kolom(men) BINARY maken
- ofwel de betreffende kolom(men) te voorzien van een binaire collation (bijvoorbeeld utf8_bin)
Oftewel, een simpele aanpassing in je database zou moeten volstaan. En waarschijnlijk is het inderdaad een goed idee om je gebruikersnaam uniek te laten zijn. Dit kun je ook afdwingen in code, door bij het registratieproces hier op te controleren.
Enkele opmerkingen over de (organisatie van je) code:
In dit login-script worden een aantal zaken samengenomen:
- sessie-management
- database-management (o.a. creatie van connectie, afhandeling van fouten)
- verwerking van formulier-input
In het kader van separation of concerns valt er misschien iets voor te zeggen om elk van deze onderdelen elk hun eigen klasse(s) te geven.
Ook als je kijkt naar de acties doLogin, doLogout, is(User)LoggedIn: dit zijn operaties die je eigenlijk op een (nog niet bestaand) gebruiker-object zou willen uitvoeren. Hier zou je weer authorisatie-operaties aan kunnen hangen etc.
De "administratieve" objecten (configuratie, database, sessie, user) zou je door kunnen geven aan klassen die deze nodig hebben, de rest zou je on-demand kunnen laden middels een autoloader.
Door deze zaken elk hun eigen plek te geven hoef je bepaalde code (bijv. het maken van een database-connectie) ook maar 1x te schrijven en blijven ze ondubbelzinnig.
Gewijzigd op 24/01/2015 15:14:20 door Thomas van den Heuvel
Ivo P op 24/01/2015 15:07:16:
Zoals ik het lees kan hij nu juist inloggen met de username
Niek
niek
NieK
etc
Niek
niek
NieK
etc
En mijn vraag is dan, is dat erg?
Ik denk dat ik liever 1 niek, ongeacht hoofdletters en kleine letters, zou prefereren boven de mogelijkheid om niek in alle variaties als username toe te laten.
Obelix en Idefix
Daar hebt je wel gelijk zo kan iemand anders zich registreren als niek.
Thomas van den Heuvel
De registratie controleerd op of de naam, wachtwoord en email al bestaan.
En de database is dit:
Code (php)
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
CREATE TABLE IF NOT EXISTS `users` (
`user_id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'auto incrementing user_id of each user, unique index',
`user_name` varchar(64) COLLATE utf8_unicode_ci NOT NULL COMMENT 'user''s name, unique',
`user_password_hash` varchar(255) COLLATE utf8_unicode_ci NOT NULL COMMENT 'user''s password in salted and hashed format',
`user_email` varchar(64) COLLATE utf8_unicode_ci NOT NULL COMMENT 'user''s email, unique',
PRIMARY KEY (`user_id`),
UNIQUE KEY `user_name` (`user_name`),
UNIQUE KEY `user_email` (`user_email`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='user data';
`user_id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'auto incrementing user_id of each user, unique index',
`user_name` varchar(64) COLLATE utf8_unicode_ci NOT NULL COMMENT 'user''s name, unique',
`user_password_hash` varchar(255) COLLATE utf8_unicode_ci NOT NULL COMMENT 'user''s password in salted and hashed format',
`user_email` varchar(64) COLLATE utf8_unicode_ci NOT NULL COMMENT 'user''s email, unique',
PRIMARY KEY (`user_id`),
UNIQUE KEY `user_name` (`user_name`),
UNIQUE KEY `user_email` (`user_email`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='user data';
Dus dat zal ook wel goed zijn, want het werkt prima
eH
ja ik kan inloggen met alle formen van niek.
maar nu iets anders ik had een registratie script met e-mail acitvatie maar nu kan ik niet testen omdat ik via localhost geen email kan verzenden. dat heeft het wel altijd gedaan, maar met php5.5 en mysqli schijnt dat niet meer te werken.
Of zou dat komen omdat vodafone mij heeft laten weten dat ze mijn account gaan stoppen per 30 maart omdat ze de snelheid via adsl niet meer kunnen garanderen, En ik heb hun via de telefoon laten weten dat ik mijn abonement per direct wou stoppen en dat gebeurt nu 13-02-2015. en zij nu alvast hun service verminderen.
Gewijzigd op 25/01/2015 00:47:59 door Niek Kasius
Die ci aan het einde: Case Insensitive toch
Dat weet ik niet. Maar ci is (meertalig) ongevoelig voor hoofdletters
Wat Ivo P bedoelt te zeggen is dat die ci (vertaald: hoofdletter-ongevoelig) ervoor zorgt dat er geen verschil is tussen Niek, NIEK, niet enzovoorts. Daarom kun je dus met allerlei varianten inloggen.
Maar dat maakt geen verschil in de uitvoering, want ik heb dat geprobeerd, door de Browsegeschiedenis te verwijderd en de Wamp server gestopt en opnieuw gestart, maar kan nog steeds inloggen met verschillende niek, Niek, niEK enz enz, Dus daar ligt het niet aan.
Maar dat maakt verder niet uit dan maar 1 Niek dus als er meer niek's komen moeten ze zich maar Niek1, Niek2 enz noemen toch. want het script controleerd op naam, wachtwoord en email adres.
Code (php)
1
2
3
4
5
2
3
4
5
<?php
$sql = "SELECT user_name, user_email, user_password_hash
FROM users
WHERE user_name = '" . $user_name . "' OR user_email = '" . $user_name . "';";
?>
$sql = "SELECT user_name, user_email, user_password_hash
FROM users
WHERE user_name = '" . $user_name . "' OR user_email = '" . $user_name . "';";
?>
Maar je selecteert op user_name OR user_email. Zodra het e-mailadres klopt, maakt het niet uit of je nu Niek, Jan, Piet of wat dan ook invult.
Gewijzigd op 25/01/2015 09:10:01 door Ward van der Put
Als de vergelijking Niek = niek onwaar oplevert dan zijn ze beiden uniek.
Ligt het aan mij of mis je ook het wachtwoord in de SELECT-query. Anders kan je met elke juiste gebruikersnaam of username inloggen, terwijl het wachtwoord buiten beschouwing wordt gelaten.
Regel 83
Dat had ik al voorgsteld.
Ik denk dat de (oorspronkelijke) vraag inmiddels wel beantwoord is trouwens...
Ik denk dat de (oorspronkelijke) vraag inmiddels wel beantwoord is trouwens...
kijk eens naar regel 70
het werkt gewoon goed.
Ik kan niet opnieuw registreren met een naam, wachtwoord of email adres dat al bestaat in de database.
Ik heb nu 3 keer geregistreerd met een andere naam, wachtwoord en emailadres, en dat werkt.
Ik kan niet inloggen met Piet met het wachtwoord van Niek.
Het script heb ik hier vandaan: https://github.com/panique/php-login-minimal/
En waarom ik wel alle vormen van 1 naam kan gebruiken weet ik niet het zal misschien wel ergens in gebouw zitten. ik weet het niet.
Maar dat maakt verder ook niet uit de hoofdzaak is dat het goed werkt.
Quote:
En waarom ik wel alle vormen van 1 naam kan gebruiken weet ik niet het zal misschien wel ergens in gebouw zitten. ik weet het niet.
Dat is hierboven uitgelegd, dat komt door de vorm van de query die je data ophaalt waarbij ook gekeken wordt naar het e-mailadres.
Zie de reactie van Ward.
Quote:
Maar je selecteert op user_name OR user_email. Zodra het e-mailadres klopt, maakt het niet uit of je nu Niek, Jan, Piet of wat dan ook invult.
Het staat er wel in regel 70.
Maar als ik de index open staat daar username en password met invul velden,
En niet met een email adres en wachtwoord.
Dus het email adres komt helemaal niet in beeld, alleen als je het opvraagt in een ander script bijvoorbeeld zoals in een ledenlijst.
ik heb geprobeerd in te loggen met een email adres en wachtwoord in plaats van gebruikersnaam en wachtwoorden dat lukt ook.
Maar ik kan niet inloggen met een naam en email want dan krijg ik een Fout wachtwoord melding
Ik heb nu Piet met pass piet123 en [email protected] en Truus met paas truus123 en [email protected] in de database staan.
En als probeer in te loggen Piet of [email protected] met het wachtwoord van Truus dan krijg ik fout wachtwoord.
Dus ik kan alleen maar inloggen met username of user_email met het daar bij behorende user_password
Dus zou ik regel 70 moeten veranderd.
Gewijzigd op 26/01/2015 00:57:40 door Niek Kasius
Het oorspronkelijke probleem was: het lijkt niet uit te maken of je de gebruikersnaam met hoofd- of kleine letters schrijft, beide worden (ten onrechte) geaccepteerd.
Speelt dat probleem nog steeds?
Je zegt dat je de database en table collation hebt veranderd naar latin1_general_cs, maar dat snijdt niet echt hout want je database-inhoud is (hopelijk) utf8. Hoe luidt nu de creatie-definitie van je users-tabel?