Benutzer:Suit/Loginsystem und Benutzerregistrierung mit PHP und MySQL

Aus SELFHTML-Wiki
Wechseln zu: Navigation, Suche

Achtung!

Artikel in Benutzernamensräumen sind möglicherweise nicht mehr aktuell oder gar fehlerhaft. Sie sind auf jeden Fall nicht Teil der offiziellen Dokumentation. Ein Großteil dieses Artikels ist inzwischen unter PHP/Tutorials/Loginsystem zu finden.

Wenn man Teile eines Internetauftritts vor neugierigen Augen schützen will, benötigt man ein wirksames System zur Zugangskontrolle. In vielen Fällen bietet sich hier die bekannte HTTP-Authentifizierung an, die man beispielsweise per .htaccess-Datei umsetzen kann. Diese Methode hat aber den Nachteil, dass es auch in modernen Browsern immer noch keine praktikable Möglichkeit gibt, sich wieder abzumelden. Ebenso können die zur Anmeldung gehörenden Informationen nicht nahtlos in die Gestaltung der Seite eingefügt werden. Dieser Artikel soll zeigen, wie man Dokumente auf relativ einfache Weise sinnvoll schützen kann. Voraussetzung dafür ist ein Webserver mit PHP- und MySQL-Unterstützung.

Vollständiger Quelltext

Benutzerdatenbank in MySQL

SQL-Tabelle für die Benutzerdaten
CREATE TABLE IF NOT EXISTS users (
  id       int(11) NOT NULL AUTO_INCREMENT,
  username varchar(255) NOT NULL,
  password varchar(255) NOT NULL,
  PRIMARY KEY (id),
  UNIQUE KEY username (username)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Registrierung von neuen Benutzern

register.php
<?php
	$message = array();
	if (!empty($_POST)) {
		if (
			empty($_POST['f']['username']) ||
			empty($_POST['f']['password']) ||
			empty($_POST['f']['password_again'])
		) {
			$message['error'] = 'Es wurden nicht alle Felder ausgefüllt.';
		} else if ($_POST['f']['password'] != $_POST['f']['password_again']) {
			$message['error'] = 'Die eingegebenen Passwörter stimmen nicht überein.';
		} else {
			unset($_POST['f']['password_again']);
			$salt = ''; 
			for ($i = 0; $i < 22; $i++) { 
				$salt .= substr('./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789', mt_rand(0, 63), 1); 
			}
			$_POST['f']['password'] = crypt(
				$_POST['f']['password'],
				'$2a$10$' . $salt
			);
			
			$mysqli = @new mysqli('localhost', 'root', '', 'loginsystem');
			if ($mysqli->connect_error) {
				$message['error'] = 'Datenbankverbindung fehlgeschlagen: ' . $mysqli->connect_error;
			}
			$query = sprintf(
				"INSERT INTO users (username, password)
				SELECT * FROM (SELECT '%s', '%s') as new_user
				WHERE NOT EXISTS (
					SELECT username FROM users WHERE username = '%s'
				) LIMIT 1;",
				$mysqli->real_escape_string($_POST['f']['username']),
				$mysqli->real_escape_string($_POST['f']['password']),
				$mysqli->real_escape_string($_POST['f']['username'])
			);
			$mysqli->query($query);
			if ($mysqli->affected_rows == 1) {
				$message['success'] = 'Neuer Benutzer (' . htmlspecialchars($_POST['f']['username']) . ') wurde angelegt, <a href="login.php">weiter zur Anmeldung</a>.';
				header('Location: http://' . $_SERVER['HTTP_HOST'] . '/login.php');
			} else {
				$message['error'] = 'Der Benutzername ist bereits vergeben.';
			}
			$mysqli->close();
		}
	} else {
		$message['notice'] = 'Übermitteln Sie das ausgefüllte Formular um ein neues Benutzerkonto zu erstellen.';
	}
?>
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title>loginsystem - register.php</title>
	</head>
	<body>
		<form action="./register.php" method="post">
<?php if (isset($message['error'])): ?>
			<fieldset class="error"><legend>Fehler</legend><?php echo $message['error'] ?></fieldset>
<?php endif;
	if (isset($message['success'])): ?>
			<fieldset class="success"><legend>Erfolg</legend><?php echo $message['success'] ?></fieldset>
<?php endif;
	if (isset($message['notice'])): ?>
			<fieldset class="notice"><legend>Hinweis</legend><?php echo $message['notice'] ?></fieldset>
<?php endif; ?>
			<fieldset>
				<legend>Benutzerdaten</legend>
				<div><label for="username">Benutzername</label> <input type="text" name="f[username]" id="username"<?php echo isset($_POST['f']['username']) ? ' value="' . htmlspecialchars($_POST['f']['username']) . '"' : '' ?> /></div>
				<div><label for="password">Kennwort</label> <input type="password" name="f[password]" id="password" /></div>
				<div><label for="password_again">Kennwort wiederholen</label> <input type="password" name="f[password_again]" id="password_again" /></div>
			</fieldset>
			<fieldset>
				<div><input type="submit" name="submit" value="Registrieren" /></div>
			</fieldset>
		</form>
	</body>
</html>

Anmelden von Benutzern

login.php
<?php
if (isset($_SESSION['login'])) {
	header('Location: http://' . $_SERVER['HTTP_HOST'] . '/index.php');
} else {
	if (!empty($_POST)) {
		if (
			empty($_POST['f']['username']) ||
			empty($_POST['f']['password'])
		) {
			$message['error'] = 'Es wurden nicht alle Felder ausgefüllt.';
		} else {
			$mysqli = @new mysqli('localhost', 'root', '', 'loginsystem');
			if ($mysqli->connect_error) {
				$message['error'] = 'Datenbankverbindung fehlgeschlagen: ' . $mysqli->connect_error;
			} else {
				$query = sprintf(
					"SELECT username, password FROM users WHERE username = '%s'",
					$mysqli->real_escape_string($_POST['f']['username'])
				);
				$result = $mysqli->query($query);
				if ($row = $result->fetch_array(MYSQLI_ASSOC)) {
					if (crypt($_POST['f']['password'], $row['password']) == $row['password']) {
						session_start();
						
						$_SESSION = array(
							'login' => true,
							'user'  => array(
								'username'  => $row['username']
							)
						);
						$message['success'] = 'Anmeldung erfolgreich, <a href="index.php">weiter zum Inhalt.';
						header('Location: http://' . $_SERVER['HTTP_HOST'] . '/index.php');
					} else {
						$message['error'] = 'Das Kennwort ist nicht korrekt.';
					}
				} else {
					$message['error'] = 'Der Benutzer wurde nicht gefunden.';
				}
				$mysqli->close();
			}
		}
	} else {
		$message['notice'] = 'Geben Sie Ihre Zugangsdaten ein um sich anzumelden.<br />' .
			'Wenn Sie noch kein Konto haben, gehen Sie <a href="./register.php">zur Registrierung</a>.';
	}
}
?>
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title>loginsystem - login.php</title>
	</head>
	<body>
		<form action="./login.php" method="post">
<?php if (isset($message['error'])): ?>
			<fieldset class="error"><legend>Fehler</legend><?php echo $message['error'] ?></fieldset>
<?php endif;
	if (isset($message['success'])): ?>
			<fieldset class="success"><legend>Erfolg</legend><?php echo $message['success'] ?></fieldset>
<?php endif;
	if (isset($message['notice'])): ?>
			<fieldset class="notice"><legend>Hinweis</legend><?php echo $message['notice'] ?></fieldset>
<?php endif; ?>
			<fieldset>
				<legend>Benutzerdaten</legend>
				<div><label for="username">Benutzername</label>
					<input type="text" name="f[username]" id="username"<?php 
					echo isset($_POST['f']['username']) ? ' value="' . htmlspecialchars($_POST['f']['username']) . '"' : '' ?> /></div>
				<div><label for="password">Kennnwort</label> <input type="password" name="f[password]" id="password" /></div>
			</fieldset>
			<fieldset>
				<div><input type="submit" name="submit" value="Anmelden" /></div>
			</fieldset>
		</form>
	</body>
</html>

Überprüfung der Sitzungsdaten

auth.php
<?php
	session_start();
	session_regenerate_id();

	if (empty($_SESSION['login'])) {
		header('Location: http://' . $_SERVER['HTTP_HOST'] . '/login.php');
		exit;
	} else {
		$login_status = '
			<div style="border: 1px solid black">
				Sie sind als <strong>' . htmlspecialchars($_SESSION['user']['username']) . '</strong> angemeldet.<br />
				<a href="./logout.php">Sitzung beenden</a>
			</div>
		';
	}
?>
index.php
<?php require_once './auth.php'; ?>
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title>loginsystem - index.php</title>
	</head>
	<body>
		<?php echo $login_status; ?>
		<h1>Inhalt</h1>
		<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr.</p>
	</body>
</html>

Abmelden und beenden einer Sitzung

logout.php
<?php
	session_start();
	$_SESSION = array();
	if (ini_get('session.use_cookies')) {
		$params = session_get_cookie_params();
		setcookie(
			session_name(),
			'',
			time() - 42000,
			$params['path'],
			$params['domain'],
			$params['secure"'],
			$params['httponly']
		);
	}
	session_destroy();
	header('Location: ./login.php');
?>