Profil | Mitglieder | Registrieren | Start | Suche


PHP-Support.de » Programmierung » PHP & MySQL » Codeschnipsel » PHP Login ab PHP 5.3.7 mit MySQLi    » Hallo Gast [Login | Registrieren]

Neues Thema | Antworten   

Autor Beitrag
Htaccess
Mitglied
Sehr guter User


Dabei seit: 22.08.2010
Herkunft: Deutschland
Posts: 742
     PHP Login ab PHP 5.3.7 mit MySQLi Zitat | Bearbeiten

Um die Grundlagen in PHP und MySQL zu vertiefen, eignen sich eigene kleine Skripte, die sich nicht auf WordPress, Typo3 etc. beziehen. In diesem Tutorial möchte ich die alte Methode des Loginsystem auf PHP-Einfach ablösen und euch auf den neusten Standard bringen.

Um diese Methode benutzen zu können ist die PHP Version 5.3.7 vorausgesetzt, denn es werden Funktionen benutzt die erst ab der PHP Version 5.5 verfügbar sind. Dank der password_compat von ircmaxell aus GitHub ist es uns aber schon möglich die benötigten Funktionen schon ab der PHP Version 5.3.7 zu verwenden.

Schritt 1: Installation und erstes Testen
Um die neue Password_* Funktionen ab der PHP Version 5.3.7 benutzen zu können, benötigen wir die Datei von ircmaxell, welche man hier downloaden kann. Nach dem Download legt ihr euch so wie ich, einen Unterordner mit dem Namen inc an und legt dort die heruntergeladene password_compat.php ab.
Nun erstellen wir uns im Hauptverzeichnis eine index.html und eine check.php an. In der check.php schreiben wir folgenden Code, direkt zu Anfang der Datei hinein:

 PHP 
1:
2:
3:
4:
5:
6:
7:
<?php
session_start
();

if ((
version_compare(PHP_VERSION'5.3.7') >= 0)
     && (
version_compare(PHP_VERSION'5.5.0') < 0)) {
    require_once(
dirname__FILE__ ) . '/inc/password_compat.php');
}

Um zu testen, ob die benötigten Funktionen nun auch enthalten sind, schreiben wir nach der If-Anweisung folgenden Code hinein:
echo password_hash('test', PASSWORD_BCRYPT);

Unser Code sieht nun folgender maßen aus:

 PHP 
1:
2:
3:
4:
5:
6:
7:
8:
9:
<?php
session_start
();

if ((
version_compare(PHP_VERSION'5.3.7') >= 0)
     && (
version_compare(PHP_VERSION'5.5.0') < 0)) {
    require_once(
dirname__FILE__ ) . '/inc/password_compat.php');
}

echo 
password_hash('test'PASSWORD_BCRYPT);


Das oben gezeigte Beispiel erzeugt eine ähnliche Ausgabe: $2y$10$ndh.9cKGK4XSU4syTyU.vemimYKxnax8VKLWD6Ucyt4q6fKP3JeqW

Wenn alles funktioniert hat, dann sind die Funktionen erfolgreich installiert. Im nächsten Schritt widmen wir uns der optimalen Konfiguration der Passwort Verschlüsselung.

Schritt 2: Optimale Konfiguration
Nach der Installation der Funktionen widmen wir uns der Konfiguration des SALT und des COST. Der SALT ist eine zufällig gewählte Zeichenfolge die im Klartext an das verschlüsselte Passwort angehängt wird, welche die Entropie der Eingabe erhöht. Der COST hingegen definiert wie oft das Passwort verschlüsselt werden soll. Um einen guten COST zu finden, empfiehlt es sich eine weitere Datei im Hauptverzeichnis zu erstellen, welche danach wieder gelöscht werden kann.

 PHP 
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
<?php
/**
 * This code will benchmark your server to determine how high of a cost you can
 * afford. You want to set the highest cost that you can without slowing down
 * you server too much. 8-10 is a good baseline, and more is good if your servers
 * are fast enough. The code below aims for > 500 milliseconds stretching time,
 * which is a good baseline for systems handling interactive logins.
 */
$timeTarget 0.5// 500 milliseconds 

$cost 4;
do {
    
$cost++;
    
$start microtime(true);
    
password_hash('test'PASSWORD_BCRYPT, ['cost' => $cost]);
    
$end microtime(true);
} while ((
$end $start) < $timeTarget);

echo 
'Appropriate Cost Found: ' $cost;
Das Ergebnis verwenden wir als COST. Als SALT empfehle ich die Verwendung von mcrypt. In meinem Beispiel haben sich folgende Einstellungen ergeben:

 PHP 
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
<?php
session_start
();

if ((
version_compare(PHP_VERSION'5.3.7') >= 0)
     && (
version_compare(PHP_VERSION'5.5.0') < 0)) {
    require_once(
dirname__FILE__ ) . '/inc/password_compat.php');
}

$options = array(
    
'cost' => 13,
    
'salt' => mcrypt_create_iv(22MCRYPT_DEV_URANDOM)
);

echo 
password_hash('test'PASSWORD_BCRYPT$options);
Das oben gezeigte Beispiel erzeugt eine ähnliche Ausgabe: $2y$09$vRtUHQJ2dldbCN0Y5iC1jOabVJcvMV243rwNagOPFT14LVxqAOtDa

Schritt 3: Das HTML Formular
Nachdem wir die benötigten Funktionen installiert und konfiguriert haben, widmen wir uns dem HTML Formular, welches später unseren Login abfragen soll. Ich verwende in diesem Beispiel ein ganz einfaches Formular, welches den Benutzernamen und das Passwort erfordert.

 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:
<!DOCTYPE html> 
<html> 
<head> 
<meta charset="utf-8"> 
<title>Mein Loginsystem</title> 
</head> 
<body style="font-family:Arial, Helvetica, sans-serif;"> 
<div style="border-radius:40px;padding:40px;background:#CCC;width:366px;box-shadow:rgba(0,0,0,.1) 5px 5px 5px;height:120px;position:absolute;top:50%;left:50%;margin-top:-150px;margin-left:-173px;"> 
<form action="check.php" method="post"> 
<div style="height:30px;"> 
<label for="benutzer" style="display:inline-block;width:48%;font-size:18px;">Benutzername:</label> 
<input type="text" name="username" id="benutzer" style="height:10px;padding:5px;"> 
</div> 
<div style="height:45px;"> 
<label for="verifikation" style="display:inline-block;width:48%;font-size:18px;">Passwort:</label> 
<input type="password" name="password" id="verifikation" style="height:10px;padding:5px;"> 
</div>
<div style="height:30px;"> 
<input type="submit" value="Einloggen!" style="height:30px;width:100%;">
</div>
</form> 
</div> 
</body> 
</html>

Schritt 4: Verifizieren mit password_verify()
In diesem Schritt schreiben wir das PHP Script um uns später authentifizieren zu können. Ich beziehe mich hierbei auf das aus Schritt 3 geschriebene HTML Formular. Als erstes stellen wir eine Abfrage, welche überprüft ob unser Formular abgesendet worden ist. Dazu gehen wir in unsere check.php und schreiben an den Anfang der Datei, noch vor dem einbinden der password_compat.php

 PHP 
1:
2:
3:
4:
5:
6:
7:
8:
<?php

if((empty(trim($_POST['username'])))
    || (empty(
$_POST['password']))) {
    exit();
}

// … Der vorher geschriebene Code

Mit dieser Abfrage überprüfen wir ob das Formular abgesendet worden ist. Für den Produktiveinsatz wird diese Methode zur Überprüfung ob das Formular abgesendet worden ist, nicht EMPFOHLEN!!! , da wir uns mit den neuen password_* Funktionen beschäftigen. Um das Passwort nun dem Usernamen zu verifizieren benutzen wir die password_verify() Funktion und fragen im nächsten Schritt ob auch das Passwort aktualisiert werden muss, weil wir zum Beispiel vor geraumer Zeit den SALT oder den COST aktualisiert haben.

 PHP 
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
<?php

if(password_verify($_POST['password'], password_hash($_POST['password'], PASSWORD_BCRYPT$options))) {
    if(
password_needs_rehash(password_hash($_POST['password'], PASSWORD_BCRYPT$options), PASSWORD_BCRYPT$options)) {
        .. 
// Neues Passwort speichern
    
}
    echo 
'Das Passwort war korrekt. Hier geht es weiter!';
} else {
    echo 
'Das Passwort war nicht korrekt. Versuche es nochmal erneut!';
}


Schritt 5: Integration von MySQL und Einrichtung
Im letzten Schritt richten wir unsere Datenbank ein und verknüpfen die Datenbank mit unserem PHP Skript, denn aktuell ist es so, dass sich jeder immer noch einloggen kann und das wollen wir verhindern.

Wir gehen also in unser PHPmyAdmin und erstellen uns eine Datenbank, die ich in meinem Beispiel passwordhash nenne. Wenn wir die Datenbank erstellt haben, führen wir folgende MySQL Abfrage durch:

Zitat:
DROP TABLE IF EXISTS `accounts`;
CREATE TABLE IF NOT EXISTS `accounts` (
`id` int(10) NOT NULL,
`user` varchar(64) NOT NULL,
`passwordhash` varchar(72) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;

ALTER TABLE `accounts`
ADD PRIMARY KEY (`id`),
MODIFY `id` int(10) NOT NULL AUTO_INCREMENT;

Nachdem wir unsere Tabelle in unsere Datenbank eingefügt haben, verbinden wir uns mit der Datenbank und lesen den abgefragten User aus.

 PHP 
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
<?php

$mysql 
= new MySQLi('localhost''BENUTZERNAME''PASSWORD''passwordhash');

if(
$mysql->connect_errno) {
    die(
$mysql->connect_error());
}

$user $mysql->query('SELECT `passwordhash` FROM `accounts` WHERE `user` = \''$_POST['username'] .'\' LIMIT 0,1');
$result $user->fetch_assoc();


Nun haben wir in der Variable $result unsere Ergebnisse und können diese in unserer Password Überprüfung ersetzen. Danach sieht unser Code folgender maßen aus:
 PHP 
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
<?php

$mysql 
= new MySQLi('localhost''BENUTZERNAME''PASSWORD''passwordhash'); 

if(
$mysql->connect_errno) { 
    die(
$mysql->connect_error()); 


$user $mysql->query('SELECT `passwordhash` FROM `accounts` WHERE `user` = \''$_POST['username'] .'\' LIMIT 0,1'); 
$result $user->fetch_assoc();

if(
password_verify($_POST['password'], $result['passwordhash'])) { 
    if(
password_needs_rehash($result['passwordhash'], PASSWORD_BCRYPT$options)) { 
        
// Neues Passwort speichern 
    
}
    
    echo 
'Das Passwort war korrekt. Hier geht es weiter!'
} else { 
    echo 
'Das Passwort war nicht korrekt. Versuche es nochmal erneut!'
}

Versuchen wir es doch mal. Wir erstellen uns einen Testaccount mit dem Namen test und dem Passwort test, wenn alles funktioniert habt ihr bis jetzt alles richtig gemacht.

Damit nun auch bei einer Aktualisierung unserer COST und unserer SALT der neue Wert in der Datenbank gespeichert wird, schreiben wir noch einen SQL Befehl, der unser Passwort aktualisieren soll, welches in die if-Anweisung von password_needs_rehash() gehört.

 PHP 
1:
2:
3:
<?php
$new_hash 
password_hash($_POST['password'], PASSWORD_BCRYPT$options);
$update $mysql->query('UPDATE `accounts` SET `passwordhash` = \''$new_hash .'\' WHERE `user` = \''$_POST['username'] .'\'');


Fertig ist unsere Login funktion und wir können uns nun Fehlerfrei anmelden.

Schritt 6: Ende, kompletter Code im Überblick
In diesem Schritt erkläre ich gar nichts, sondern gebe euch nochmal den kompletten Code in der Übersicht.

inc/password_compat.php
 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:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
183:
184:
185:
186:
187:
188:
189:
190:
191:
192:
193:
194:
195:
196:
197:
198:
199:
200:
201:
202:
203:
204:
205:
206:
207:
208:
209:
210:
211:
212:
213:
214:
215:
216:
217:
218:
219:
220:
221:
222:
223:
224:
225:
226:
227:
228:
229:
230:
231:
232:
233:
234:
235:
236:
237:
238:
239:
240:
241:
242:
243:
244:
245:
246:
247:
248:
249:
250:
251:
252:
253:
254:
255:
256:
257:
258:
259:
260:
261:
262:
263:
264:
265:
266:
267:
268:
269:
270:
271:
272:
273:
274:
275:
276:
277:
278:
279:
280:
281:
282:
283:
284:
285:
286:
287:
288:
289:
290:
291:
292:
<?php
/**
 * A Compatibility library with PHP 5.5's simplified password hashing API.
 *
 * @author Anthony Ferrara <ircmaxell@php.net>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @copyright 2012 The Authors
 */
namespace {
    if (!
defined('PASSWORD_BCRYPT')) {
        
/**
         * PHPUnit Process isolation caches constants, but not function declarations.
         * So we need to check if the constants are defined separately from 
         * the functions to enable supporting process isolation in userland
         * code.
         */
        
define('PASSWORD_BCRYPT'1);
        
define('PASSWORD_DEFAULT'PASSWORD_BCRYPT);
        
define('PASSWORD_BCRYPT_DEFAULT_COST'10);
    }
    if (!
function_exists('password_hash')) {
        
/**
         * Hash the password using the specified algorithm
         *
         * @param string $password The password to hash
         * @param int    $algo     The algorithm to use (Defined by PASSWORD_* constants)
         * @param array  $options  The options for the algorithm to use
         *
         * @return string|false The hashed password, or false on error.
         */
        
function password_hash($password$algo, array $options = array()) {
            if (!
function_exists('crypt')) {
                
trigger_error("Crypt must be loaded for password_hash to function"E_USER_WARNING);
                return 
null;
            }
            if (
is_null($password) || is_int($password)) {
                
$password = (string) $password;
            }
            if (!
is_string($password)) {
                
trigger_error("password_hash(): Password must be a string"E_USER_WARNING);
                return 
null;
            }
            if (!
is_int($algo)) {
                
trigger_error("password_hash() expects parameter 2 to be long, " gettype($algo) . " given"E_USER_WARNING);
                return 
null;
            }
            
$resultLength 0;
            switch (
$algo) {
                case 
PASSWORD_BCRYPT:
                    
$cost PASSWORD_BCRYPT_DEFAULT_COST;
                    if (isset(
$options['cost'])) {
                        
$cost $options['cost'];
                        if (
$cost || $cost 31) {
                            
trigger_error(sprintf("password_hash(): Invalid bcrypt cost parameter specified: %d"$cost), E_USER_WARNING);
                            return 
null;
                        }
                    }
                    
// The length of salt to generate
                    
$raw_salt_len 16;
                    
// The length required in the final serialization
                    
$required_salt_len 22;
                    
$hash_format sprintf("$2y$%02d$"$cost);
                    
// The expected length of the final crypt() output
                    
$resultLength 60;
                    break;
                default:
                    
trigger_error(sprintf("password_hash(): Unknown password hashing algorithm: %s"$algo), E_USER_WARNING);
                    return 
null;
            }
            
$salt_req_encoding false;
            if (isset(
$options['salt'])) {
                switch (
gettype($options['salt'])) {
                    case 
'NULL':
                    case 
'boolean':
                    case 
'integer':
                    case 
'double':
                    case 
'string':
                        
$salt = (string) $options['salt'];
                        break;
                    case 
'object':
                        if (
method_exists($options['salt'], '__tostring')) {
                            
$salt = (string) $options['salt'];
                            break;
                        }
                    case 
'array':
                    case 
'resource':
                    default:
                        
trigger_error('password_hash(): Non-string salt parameter supplied'E_USER_WARNING);
                        return 
null;
                }
                if (
PasswordCompat\binary\_strlen($salt) < $required_salt_len) {
                    
trigger_error(sprintf("password_hash(): Provided salt is too short: %d expecting %d"PasswordCompat\binary\_strlen($salt), $required_salt_len), E_USER_WARNING);
                    return 
null;
                } elseif (
== preg_match('#^[a-zA-Z0-9./]+$#D'$salt)) {
                    
$salt_req_encoding true;
                }
            } else {
                
$buffer '';
                
$buffer_valid false;
                if (
function_exists('mcrypt_create_iv') && !defined('PHALANGER')) {
                    
$buffer mcrypt_create_iv($raw_salt_lenMCRYPT_DEV_URANDOM);
                    if (
$buffer) {
                        
$buffer_valid true;
                    }
                }
                if (!
$buffer_valid && function_exists('openssl_random_pseudo_bytes')) {
                    
$buffer openssl_random_pseudo_bytes($raw_salt_len);
                    if (
$buffer) {
                        
$buffer_valid true;
                    }
                }
                if (!
$buffer_valid && @is_readable('/dev/urandom')) {
                    
$file fopen('/dev/urandom''r');
                    
$read PasswordCompat\binary\_strlen($buffer);
                    while (
$read $raw_salt_len) {
                        
$buffer .= fread($file$raw_salt_len $read);
                        
$read PasswordCompat\binary\_strlen($buffer);
                    }
                    
fclose($file);
                    if (
$read >= $raw_salt_len) {
                        
$buffer_valid true;
                    }
                }
                if (!
$buffer_valid || PasswordCompat\binary\_strlen($buffer) < $raw_salt_len) {
                    
$buffer_length PasswordCompat\binary\_strlen($buffer);
                    for (
$i 0$i $raw_salt_len$i++) {
                        if (
$i $buffer_length) {
                            
$buffer[$i] = $buffer[$i] ^ chr(mt_rand(0255));
                        } else {
                            
$buffer .= chr(mt_rand(0255));
                        }
                    }
                }
                
$salt $buffer;
                
$salt_req_encoding true;
            }
            if (
$salt_req_encoding) {
                
// encode string with the Base64 variant used by crypt
                
$base64_digits =
                    
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
                
$bcrypt64_digits =
                    
'./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
                
$base64_string base64_encode($salt);
                
$salt strtr(rtrim($base64_string'='), $base64_digits$bcrypt64_digits);
            }
            
$salt PasswordCompat\binary\_substr($salt0$required_salt_len);
            
$hash $hash_format $salt;
            
$ret crypt($password$hash);
            if (!
is_string($ret) || PasswordCompat\binary\_strlen($ret) != $resultLength) {
                return 
false;
            }
            return 
$ret;
        }
        
/**
         * Get information about the password hash. Returns an array of the information
         * that was used to generate the password hash.
         *
         * array(
         *    'algo' => 1,
         *    'algoName' => 'bcrypt',
         *    'options' => array(
         *        'cost' => PASSWORD_BCRYPT_DEFAULT_COST,
         *    ),
         * )
         *
         * @param string $hash The password hash to extract info from
         *
         * @return array The array of information about the hash.
         */
        
function password_get_info($hash) {
            
$return = array(
                
'algo' => 0,
                
'algoName' => 'unknown',
                
'options' => array(),
            );
            if (
PasswordCompat\binary\_substr($hash04) == '$2y$' && PasswordCompat\binary\_strlen($hash) == 60) {
                
$return['algo'] = PASSWORD_BCRYPT;
                
$return['algoName'] = 'bcrypt';
                list(
$cost) = sscanf($hash"$2y$%d$");
                
$return['options']['cost'] = $cost;
            }
            return 
$return;
        }
        
/**
         * Determine if the password hash needs to be rehashed according to the options provided
         *
         * If the answer is true, after validating the password using password_verify, rehash it.
         *
         * @param string $hash    The hash to test
         * @param int    $algo    The algorithm used for new password hashes
         * @param array  $options The options array passed to password_hash
         *
         * @return boolean True if the password needs to be rehashed.
         */
        
function password_needs_rehash($hash$algo, array $options = array()) {
            
$info password_get_info($hash);
            if (
$info['algo'] != $algo) {
                return 
true;
            }
            switch (
$algo) {
                case 
PASSWORD_BCRYPT:
                    
$cost = isset($options['cost']) ? $options['cost'] : PASSWORD_BCRYPT_DEFAULT_COST;
                    if (
$cost != $info['options']['cost']) {
                        return 
true;
                    }
                    break;
            }
            return 
false;
        }
        
/**
         * Verify a password against a hash using a timing attack resistant approach
         *
         * @param string $password The password to verify
         * @param string $hash     The hash to verify against
         *
         * @return boolean If the password matches the hash
         */
        
function password_verify($password$hash) {
            if (!
function_exists('crypt')) {
                
trigger_error("Crypt must be loaded for password_verify to function"E_USER_WARNING);
                return 
false;
            }
            
$ret crypt($password$hash);
            if (!
is_string($ret) || PasswordCompat\binary\_strlen($ret) != PasswordCompat\binary\_strlen($hash) || PasswordCompat\binary\_strlen($ret) <= 13) {
                return 
false;
            }
            
$status 0;
            for (
$i 0$i PasswordCompat\binary\_strlen($ret); $i++) {
                
$status |= (ord($ret[$i]) ^ ord($hash[$i]));
            }
            return 
$status === 0;
        }
    }
}
namespace 
PasswordCompat\binary {
    if (!
function_exists('PasswordCompat\\binary\\_strlen')) {
        
/**
         * Count the number of bytes in a string
         *
         * We cannot simply use strlen() for this, because it might be overwritten by the mbstring extension.
         * In this case, strlen() will count the number of *characters* based on the internal encoding. A
         * sequence of bytes might be regarded as a single multibyte character.
         *
         * @param string $binary_string The input string
         *
         * @internal
         * @return int The number of bytes
         */
        
function _strlen($binary_string) {
            if (
function_exists('mb_strlen')) {
                return 
mb_strlen($binary_string'8bit');
            }
            return 
strlen($binary_string);
        }
        
/**
         * Get a substring based on byte limits
         *
         * @see _strlen()
         *
         * @param string $binary_string The input string
         * @param int    $start
         * @param int    $length
         *
         * @internal
         * @return string The substring
         */
        
function _substr($binary_string$start$length) {
            if (
function_exists('mb_substr')) {
                return 
mb_substr($binary_string$start$length'8bit');
            }
            return 
substr($binary_string$start$length);
        }
        
/**
         * Check if current PHP version is compatible with the library
         *
         * @return boolean the check result
         */
        
function check() {
            static 
$pass NULL;
            if (
is_null($pass)) {
                if (
function_exists('crypt')) {
                    
$hash '$2y$04$usesomesillystringfore7hnbRJHxXVLeakoG8K30oukPsA.ztMG';
                    
$test crypt("password"$hash);
                    
$pass $test == $hash;
                } else {
                    
$pass false;
                }
            }
            return 
$pass;
        }
    }
}


index.html
 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:
<!DOCTYPE html> 
<html> 
<head> 
<meta charset="utf-8"> 
<title>Mein Loginsystem</title> 
</head> 
<body style="font-family:Arial, Helvetica, sans-serif;"> 
<div style="border-radius:40px;padding:40px;background:#CCC;width:366px;box-shadow:rgba(0,0,0,.1) 5px 5px 5px;height:120px;position:absolute;top:50%;left:50%;margin-top:-150px;margin-left:-173px;"> 
<form action="check.php" method="post"> 
<div style="height:30px;"> 
<label for="benutzer" style="display:inline-block;width:48%;font-size:18px;">Benutzername:</label> 
<input type="text" name="username" id="benutzer" style="height:10px;padding:5px;"> 
</div> 
<div style="height:45px;"> 
<label for="verifikation" style="display:inline-block;width:48%;font-size:18px;">Passwort:</label> 
<input type="password" name="password" id="verifikation" style="height:10px;padding:5px;"> 
</div>
<div style="height:30px;"> 
<input type="submit" value="Einloggen!" style="height:30px;width:100%;">
</div>
</form> 
</div> 
</body> 
</html>


costs.php
 PHP 
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
<?php 
/** 
 * This code will benchmark your server to determine how high of a cost you can 
 * afford. You want to set the highest cost that you can without slowing down 
 * you server too much. 8-10 is a good baseline, and more is good if your servers 
 * are fast enough. The code below aims for > 500 milliseconds stretching time, 
 * which is a good baseline for systems handling interactive logins. 
 */ 
$timeTarget 0.5// 500 milliseconds  

$cost 4
do { 
    
$cost++; 
    
$start microtime(true); 
    
password_hash('test'PASSWORD_BCRYPT, ['cost' => $cost'salt' => mcrypt_create_iv(22MCRYPT_DEV_URANDOM)]); 
    
$end microtime(true);
} while ((
$end $start) < $timeTarget); 

echo 
'Appropriate Cost Found: ' $cost;


check.php
 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:
<?php 
session_start
(); 

if((empty(
trim($_POST['username']))) 
    || (empty(
$_POST['password']))) { 
    exit(); 


if ((
version_compare(PHP_VERSION'5.3.7') >= 0)
     && (
version_compare(PHP_VERSION'5.5.0') < 0)) {
    require_once(
dirname__FILE__ ) . '/inc/password_compat.php'); 


$options = array( 
    
'cost' => 13
    
'salt' => mcrypt_create_iv(22MCRYPT_DEV_URANDOM
); 

$mysql = new MySQLi('localhost''BENUTZERNAME''PASSWORD''passwordhash'); 

if(
$mysql->connect_errno) { 
    die(
$mysql->connect_error()); 


$user $mysql->query('SELECT `passwordhash` FROM `accounts` WHERE `user` = \''$_POST['username'] .'\' LIMIT 0,1'); 
$result $user->fetch_assoc();

if(
password_verify($_POST['password'], $result['passwordhash'])) { 
    if(
password_needs_rehash($result['passwordhash'], PASSWORD_BCRYPT$options)) {
        
$new_hash password_hash($_POST['password'], PASSWORD_BCRYPT$options);
        
$update $mysql->query('UPDATE `accounts` SET `passwordhash` = \''$new_hash .'\' WHERE `user` = \''$_POST['username'] .'\'');
    }
    
    echo 
'Das Passwort war korrekt. Hier geht es weiter!'
} else { 
    echo 
'Das Passwort war nicht korrekt. Versuche es nochmal erneut!'
}


Ich wünsche euch viel Spaß damit. Wir werden uns wiedersehen. Demnächst programmiere ich ein von mir geschaffenes Tool, perfekt geeignet für Anfänger

~ Bis dahin.

Du hast Tipps und Anregungen, was ich besser machen kann? Ich habe nehme jede konstruktive Kritik gerne an.




Post wurde schon 5x editiert, das letzte mal am 03.03.2015 um 13:21 von Htaccess
23.02.2015, 17:24 Profil | PM | E-Mail  
FalkenaugeMihawk
Mitglied
Perfekter User


Dabei seit: 05.06.2010
Herkunft: Schweiz
Posts: 2619
      Zitat | Bearbeiten

Du solltest vielleicht prüfen, bevor du die password_compat.php einbindest, ob der jenige eventuell bereits PHP 5.5 verwendet. Denn dann benötigt man die entsprechende Datei nicht und verhindert auch so Fehlermeldungen.


25.02.2015, 00:15 Profil | PM | E-Mail  
Htaccess
Mitglied
Sehr guter User


Dabei seit: 22.08.2010
Herkunft: Deutschland
Posts: 742
      Zitat | Bearbeiten

Ja stimmt... Muss ich nur ein UND-OPERATOR setzen der sagt, wenn die PHP Version unter 5.5 ist

Vielen dank, daran habe ich zum gegebenen Zeitpunkt nicht gedacht, war schon spät als ich das Script geschrieben habe^^

Ich werde es bei Zeiten hinzufügen

NACHTRAG: Es ist hinzugefügt.




Post wurde schon 1x editiert, das letzte mal am 03.03.2015 um 13:22 von Htaccess
25.02.2015, 11:26 Profil | PM | E-Mail  
Karamba
Mitglied
Neuling


Dabei seit: 12.10.2007
Herkunft: keine Angabe
Posts: 4
      Zitat | Bearbeiten

Wird nicht bei der Funktion password_hash das Salz automatisch hinzugefügt?

Karamba


03.08.2015, 13:55 Profil | PM | E-Mail  
FalkenaugeMihawk
Mitglied
Perfekter User


Dabei seit: 05.06.2010
Herkunft: Schweiz
Posts: 2619
      Zitat | Bearbeiten

Zitat:
Orginal von Karamba
Wird nicht bei der Funktion password_hash das Salz automatisch hinzugefügt?

Karamba

Ja, aber den Salt der in der $options ist. Und den Salt sollte man wie es Htaccess auch macht mit der mcrypt Funktion generieren.


03.08.2015, 14:58 Profil | PM | E-Mail  
DingsDaBums
Mitglied
Exzellenter User


Dabei seit: 12.09.2010
Herkunft: keine Angabe
Posts: 2496
      Zitat | Bearbeiten

Zitat:
Orginal von FalkenaugeMihawk
Zitat:
Orginal von Karamba
Wird nicht bei der Funktion password_hash das Salz automatisch hinzugefügt?

Karamba

Ja, aber den Salt der in der $options ist. Und den Salt sollte man wie es Htaccess auch macht mit der mcrypt Funktion generieren.


Nein, den Salt sollte man allgemein NICHT selbst generieren, wenn man die password_hash Funktion verwendet.

Zitat:
Caution:
It is strongly recommended that you do not generate your own salt for this function. It will create a secure salt automatically for you if you do not specify one.

(http://www.php.net/manual/en/function.password-hash.php)


Schau mal bei meinem Projekt vorbei. Vielleicht ist das ja was für dich MyStartPanel - Deine persönliche Startseite mit deinen Favoriten
Auf der Suche nach einem guten Vokabeltrainer? Vokabeltrainer Cramfire - Schnell und effektiv Vokabeln lernen

Post wurde schon 1x editiert, das letzte mal am 03.08.2015 um 23:08 von DingsDaBums
03.08.2015, 23:06 Profil | PM | E-Mail  
DingsDaBums
Mitglied
Exzellenter User


Dabei seit: 12.09.2010
Herkunft: keine Angabe
Posts: 2496
      Zitat | Bearbeiten

Zitat:
Orginal von FalkenaugeMihawk
Du solltest vielleicht prüfen, bevor du die password_compat.php einbindest, ob der jenige eventuell bereits PHP 5.5 verwendet. Denn dann benötigt man die entsprechende Datei nicht und verhindert auch so Fehlermeldungen.


Diesen Beitrag habe ich erst jetzt gesehen, weil ich mir letztens nicht den kompletten Thread durchgelesen habe, deswegen erst jetzt meine Antwort darauf ^^

Wieso muss man vorher prüfen, ob PHP 5.5+ vorhanden ist, bevor man das Skript hinzufügt?
Wenn man sich das Skript mal wirklich anschaut, erkennt man, dass die entsprechenden Konstanten und Funktionen nur dann definiert werden, wenn PASSWORD_BCRYPT und password_hash() NICHT existieren. Dieses Skript ist extra darauf ausgelegt, dass es sich "selbst abschaltet", sobald man es nicht mehr braucht, damit es eben nicht zu gewissen Fehlermeldungen kommt.

Dieses Update der Prüfung auf die aktuelle Version ist somit eigentlich unnötig und verstehe nicht, welche Fehlermeldungen da kommen sollten, wenn man dann später mal PHP 5.5+ verwenden sollte, während man dieses Skript weiterhin einbindet.


Schau mal bei meinem Projekt vorbei. Vielleicht ist das ja was für dich MyStartPanel - Deine persönliche Startseite mit deinen Favoriten
Auf der Suche nach einem guten Vokabeltrainer? Vokabeltrainer Cramfire - Schnell und effektiv Vokabeln lernen
09.09.2015, 10:03 Profil | PM | E-Mail  
Marlight
Mitglied
Guter User


Dabei seit: 19.09.2011
Herkunft: Deutschland, Bergkamen
Posts: 435
      Zitat | Bearbeiten

Hallöchen

ich habe mal eine Frage bezüglich des "salt" ab PHP7.0.
Wenn ich dies verwende gibt er mir die Meldung aus, das dieses veraltet sei.

Zitat:
WARNING password_hash(): Use of the 'salt' option to password_hash is deprecated on line number 9


Soll man den "salt" dann einfach weg lassen?


16.10.2016, 13:36 Profil | PM | Homepage | E-Mail  
DingsDaBums
Mitglied
Exzellenter User


Dabei seit: 12.09.2010
Herkunft: keine Angabe
Posts: 2496
      Zitat | Bearbeiten

Zitat:
Orginal von Marlight
Hallöchen

ich habe mal eine Frage bezüglich des "salt" ab PHP7.0.
Wenn ich dies verwende gibt er mir die Meldung aus, das dieses veraltet sei.

Zitat:
WARNING password_hash(): Use of the 'salt' option to password_hash is deprecated on line number 9


Soll man den "salt" dann einfach weg lassen?


Ja, man sollte auch vorher den Salt nicht selbst setzen, weil PHP schon automatisch selbst einen möglich sicheren Salt generiert, wenn man keinen Salt angibt. Entsprechend konnte man den Salt höchstens genau so sicher, aber eher unsicherer machen, wenn man ihn selbst geniert hat, weswegen diese Option auch veraltet ist und bald sicher komplett entfernt wird.

Edit:
Zitat:
Caution
It is strongly recommended that you do not generate your own salt for this function. It will create a secure salt automatically for you if you do not specify one.
As noted above, providing the salt option in PHP 7.0 will generate a deprecation warning. Support for providing a salt manually may be removed in a future PHP release.

Quelle: http://php.net/manual/en/function.password-hash.php


Schau mal bei meinem Projekt vorbei. Vielleicht ist das ja was für dich MyStartPanel - Deine persönliche Startseite mit deinen Favoriten
Auf der Suche nach einem guten Vokabeltrainer? Vokabeltrainer Cramfire - Schnell und effektiv Vokabeln lernen

Post wurde schon 1x editiert, das letzte mal am 16.10.2016 um 19:41 von DingsDaBums
16.10.2016, 19:39 Profil | PM | E-Mail  
Seiten (1):  1 
PHP-Support.de » Programmierung » PHP & MySQL » Codeschnipsel » PHP Login ab PHP 5.3.7 mit MySQLi   

Neues Thema | Antworten   


Powered by Command Board 1.0 - Beta 2.0 © 2004-08 PHP-Einfach | Impressum | Datenschutz