Hi,
ich hab mir mal vor einiger Zeit eine Login Klasse erstellt bzw. von einem Tutorial übernommen und weiterverbreitet.
Jetzt würd mich mal interessieren ob man da noch was verbessern könnte sowohl an der performance als auch an der Sicherheit.
Kurz zur Klasse: das $Config Array hab ich in eine extra Datei gepackt, welche auch eingebunden wird. Unter der Klasse ist noch ein kleines Anwendungsbeispiel.
Ich würd mich über einen kurzen Blick darauf freuen.
Das wäre mal die login.class.php:
----------------------------------
<?php
class Login {
public $UserId = 0;
public $Username = "";
public $Password = "";
private $Salt = "";
private $Config = array();
private $DBConnection = NULL;
private $DBSelected = NULL;
private $DBError = "";
public function __construct($Config) {
$this->Config = $Config;
ini_set('session.use_only_cookies', '1');
ini_set('session.use_trans_sid', '0');
if ($this->Config['Notices']) {
error_reporting(E_ALL|E_STRICT);
ini_set('display_errors', '1');
} else {
error_reporting(0);
ini_set('display_errors', '0');
}
if($this->DBConnection === NULL) {
$this->DBConnect();
} else {
$this->DBCheckCon();
}
}
private function DBConnect() {
if($this->DBConnection !== NULL) {
$this->DBCheckCon();
return TRUE;
}
$this->DBConnection = new mysqli($this->Config['DBHost'], $this->Config['DBUser'], $this->Config['DBPass'], $this->Config['DBName']);
if (mysqli_connect_error()) {
$this->DBError = 'Connect Error (' . mysqli_connect_errno() . ') '.mysqli_connect_error()." in <b>". __CLASS__ ."::". __FUNCTION__ ."</b>";
$this->DBConnection = NULL;
$this->DBDebug();
return FALSE;
}
return TRUE;
}
private function DBCheckCon() {
if(!$this->DBConnection->ping()) {
$this->DBConnection = NULL;
$this->DBConnect();
}
}
private function DBDebug() {
if($this->Config['Debug']) {
echo $this->DBError;
}
return TRUE;
}
function LoginUserAuth($User, $Pass, $FromCookie = FALSE) {
$this->DbCheckCon();
$Query = 'SELECT
`ID`,
`UserId`,
`alias`,
`password`,
`rights`,
`salt`,
`cookie_hash`
FROM
`'.$this->Config['TablePrefix'].'user`
WHERE
LOWER(`alias`) = LOWER(?)';
$Insert = $this->DBConnection->stmt_init();
if(!$Insert->prepare($Query)) {
$this->DBError = 'Query Error (' . $Insert->errno . ') '.$Insert->error." in <b>". __CLASS__ ."::". __FUNCTION__ ."</b>";
$this->DBDebug();
}
$Insert->bind_param('s', $User);
$Insert->execute();
$Insert->store_result();
$NumRows = $Insert->num_rows;
if($NumRows == 1) {
$Insert->bind_result($DBID, $DBUserId, $DBAlias, $DBPass, $DBRights, $DBSalt, $DBCookieHash);
$Insert->fetch();
if($FromCookie) {
if($DBCookieHash != $Pass) {
return FALSE;
}
} else {
if($DBPass != md5($Pass.$DBSalt.$this->Config['LoginStaticSalt'])) {
return FALSE;
}
}
$this->UserId = $DBUserId;
$this->Username = $DBAlias;
$this->Password = $DBPass;
$this->Rights = $DBRights;
$this->Salt = $DBSalt;
$Insert->close();
return TRUE;
}
return FALSE;
}
function LoginUser($User, $Pass, $StayLoggedIn = FALSE) {
if(get_magic_quotes_gpc()) {
$User = stripslashes($User);
$Pass = stripslashes($Pass);
}
$User = trim($User);
$UserAuth = $this->LoginUserAuth($User, $Pass);
if($UserAuth) {
if($StayLoggedIn) {
$this->CookieSetup($this->Username, $this->GenerateHash(32));
}
$this->SessionSetup($User);
usleep(rand(500000,1500000));
return TRUE;
}
sleep(rand(2,4));
return FALSE;
}
function LoginCheck() {
if(isset($_COOKIE[$this->Config['CookieName'].'user_login'])) {
$String = $_COOKIE[$this->Config['CookieName'].'user_login'];
$Explode = explode($this->Config['CookieSeperator'], $String);
if(is_array($Explode)) {
$User = $Explode[0];
$Hash = $Explode[1];
} else {
echo "Fehler beim Auslesen des Cookies!";
return FALSE;
}
if($this->LoginUserAuth($User, $Hash, TRUE)) {
return TRUE;
}
}
if(isset($_SESSION['UserData'])) {
if(isset($_SESSION['UserData']['Name']) AND $_SESSION['UserData']['Name'] === $this->Username AND isset($_SESSION['UserData']['Login']) AND $_SESSION['UserData']['Login']) {
return TRUE;
}
}
return FALSE;
}
function Logout() {
if(isset($_COOKIE[$this->Config['CookieName'].'user_login'])) {
$this->CookiesDestroy();
}
$this->SessionDestroy();
header('Location: index.php');
}
function CookieSetup($User, $Hash) {
$CookieString = $User.$this->Config['CookieSeperator'].$Hash;
setcookie($this->Config['CookieName'].'user_login', $CookieString, time() + $this->Config['CookieTimeout'], $this->Config['CookiePath']);
$Query = 'UPDATE `'.$this->Config['TablePrefix'].'user` SET `cookie_hash` = ? WHERE LOWER(`alias`) = LOWER(?)';
$Insert = $this->DBConnection->stmt_init();
if(!$Insert->prepare($Query)) {
$this->DBError = "Query Error in <b>". __CLASS__ ."::". __FUNCTION__ ."</b>";
$this->DBDebug();
}
$Insert->bind_param('ss', $Hash, $User);
$Insert->execute();
$Insert->close();
return TRUE;
}
function SessionSetup($User) {
$_SESSION['UserData']['Name'] = $User;
$_SESSION['UserData']['UserId'] = $this->UserId;
$_SESSION['UserData']['Rights'] = $this->Rights;
$_SESSION['UserData']['Login'] = TRUE;
return TRUE;
}
private function CookiesDestroy() {
setcookie($this->Config['CookieName'].'user_login', '', 0, $this->Config['CookiePath']);
return TRUE;
}
private function SessionDestroy() {
session_unset();
$_SESSION = array();
session_destroy();
return TRUE;
}
private function GenerateHash($HashSize) {
$Hash = "";
srand((double)microtime()*1000000);
for($i=0; $i < $HashSize; $i++) {
$Number = rand(48,120);
while (($Number >= 58 && $Number <= 64) || ($Number >= 91 && $Number <= 96)) {
$Number = rand(48,120);
}
$Hash .= chr($Number);
}
return $Hash;
}
}
?>
--------------------------------------------------------------------------
--------------------------------------------------------------------------
--------------------------------------------------------------------------
--------------------------------------------------------------------------
und hier das Ganze mal in Verwendung:
<?php
//Klasse einbinden
//$Config einbinden
ob_start();
$Login = new Login($Config);
session_start();
if (!isset( $_SESSION['server_SID'] )) {
session_unset();
$_SESSION = array();
session_destroy();
session_start();
session_regenerate_id();
$_SESSION['server_SID'] = TRUE;
}
if(isset($_GET['logout']) && ($_GET['logout'] == "true")) {
$Login->Logout();
}
if(isset($_POST['Submit'])) {
if($Login->LoginUser($_POST['UName'], $_POST['UPass'], TRUE)) {
//Login Erfolgreich
} else {
//Login nicht Erfolgreich
}
}
//Formular
ob_end_flush();
?>