Hello Alex,
bin zwar nicht der mit der Einstiegsfrage, aber mich würde das von dir bevorzugte requestbasierte Loginsystem weiter interessieren?
Was genau ist darunter zu verstehen?
Ich habe z.B. eine MySQL-Tabelle mit id, name, password. Jetzt kommt wer und loggt sich ein. Ich vergleiche seine Eingaben mit denen in der Tabelle. Wie geht es dann weiter, wenn es passt? Wo speichere ich, dass der User eingeloggt ist? Gebe ich die Logininformationen einfach per Post von Seite zu Seite weiter? Marker ich in der Tabelle einen aktiven Nutzer (bspw. mit einer weiteren Spalte "aktiv")?
Du benötigst als Basis des Ganzen nach wie vor eine (gültige) Session.
Die Gültigkeitsdauer der Sessiondatei (deren Existenz) sollte LOGIN_MAX + x Sekunden betragen, also auf jeden Fall länger sein, als die vorgesehene maximale "Loginzeit" ohne Retrigger, also ohne Request des Users.
Bei jedem Request des Users wird eine Datenbankabfrage vorgenommen, ob dort die Sessionnummer eingetragen ist mit gültigen Grenzen für Last-Request-Time, This-Request-Time und Max-Login-Time und wenn Du willst, auch noch First-Login-Time
Dies erfordert mindestens zwei Funktionen:
- login()
- is_logged()
Die könnten in etwa so aussehen:
#------------------------------------------------------------------------------------------------------
function login()
{
$con = get_db_con(true);
$logout = logout();
if (!session_regenerate_id ()) return false;
# die('Function login(), Connection: ' . (htmlspecialchars(print_r($con,1)))); ## fehlt ...
if (!$con) return false;
$qry_login = "update `login`
set
session = '" . session_id() . "',
lastclick = now(),
sessionstart = now(),
clickcount = clickcount + 1
where
nickname = '" . mysqli_real_escape_string($con, $_POST['data']['nickname'])."' and
password = '" . md5($_POST['data']['password'])."' and
status > 0";
$res = mysqli_query($con, $qry_login);
# die('Function login(), MySQL-Error: ' . mysql_error($con));
if (mysqli_affected_rows($con) == 1)
{
$_SESSION['nickname'] = $_POST['data']['nickname'];
$_SESSION['sess_start'] = get_time();
$_SESSION['lastclick'] = get_time();
return 'Angemeldet als ' . htmlspecialchars($_SESSION['nickname']);
}
return false;
}
#------------------------------------------------------------------------------------------------------
function is_logged()
{
$con = get_db_con(true);
if (!$con) return false;
$qry_is_logged = "
update `login`
set
lastclick = now(),
clickcount = clickcount +1
where
session = '" . session_id() . "' and
(now() - lastclick < " . SESS_MAXTIME . ")";
$res = mysqli_query($con, $qry_is_logged);
if (mysqli_affected_rows($con) === 1)
{
$_SESSION['lastclick'] = get_time();
return htmlspecialchars($_SESSION['nickname']);
}
elseif (mysqli_affected_rows($con) === -1)
{
return 'Is_logged(): Fehler im Update-Statement';
}
return false;
}
und ggf. noch eine dritte fürs "Logout"
#------------------------------------------------------------------------------------------------------
function logout()
{
$con = get_db_con();
if (!$con) return false;
$qry_logout = "
update `login`
set
session = '" . 'invalid:'.get_time() ."',
lastclick = 0,
clickcount = clickcount +1
where
session = '" . session_id() ."'";
$res = mysqli_query($con, $qry_logout);
if (mysqli_affected_rows($con) === 1)
{
unset($_SESSION['starttime']);
$_SESSION['sess_end'] = get_time();
$_SESSION['lastclick'] = get_time();
return htmlspecialchars($_SESSION['nickname']) . ' wurde erfolgreich abgemeldet.';
}
return false;
}
Dieses Verfahren hat dann den Vorteil, dass man den User auch während einer Session "rausschmeißen" kann, denn das ist meistens notwenig, wenn Verfehlungen festgestellt werden.
Die "PHP-SESSION" würde sich ja sonst endlos verlängern mit jedem Request.
Und man kann eine "Wer ist online"-Liste erzeugen:
function who_is_online()
{
# static $time, $_online_list; ## nur einmal pro Sekunde neu aufbauen!
###### Baustelle
$con = get_db_con(true);
if (!$con) return false;
$qry_who_is_online = "
select
id,
now() - lastclick as seconds,
nickname,
lastname,
firstname,
email
from `login`
where
now() - lastclick < " . SESS_MAXTIME ."
order by seconds";
$res = mysqli_query($con, $qry_who_is_online);
if ($res)
{
$_online_list = false;
$no = 1;
while ($_record = mysqli_fetch_assoc($res))
{
$_online_list['id'][$no] = $_record['id'];
$_online_list['nickname'][$no] = $_record['nickname'];
$_online_list['seconds'][$no] = $_record['seconds'];
$_online_list['lastname'][$no] = $_record['lastname'];
$_online_list['firstname'][$no] = $_record['firstname'];
$_online_list['email'][$no] = $_record['email'];
$no++;
}
return $_online_list;
}
return false;
}
Ich hatte da neulich selber ein paar Fragen hinterlassen zur obigen Baustelle, da das "who is online" nicht bei jedem Request jedes Users neu aufgebaut werden müsste, sondern nur z. B. einmal pro Sekunde für das gesamte System.
Die MySQL-Tabelle sieht bisher so aus (noch nicht weiter überprüft):
CREATE TABLE `login` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`lastclick` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`clickcount` bigint(20) NOT NULL,
`createdate` datetime NOT NULL,
`sessionstart` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
`session` varchar(50) NOT NULL,
`lastupdate` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
`nickname` varchar(50) NOT NULL,
`lastname` varchar(50) NOT NULL,
`password` varchar(50) NOT NULL,
`firstname` varchar(50) NOT NULL,
`email` varchar(50) NOT NULL,
`status` int(11) NOT NULL DEFAULT '0',
`level` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY `nickname` (`nickname`),
UNIQUE KEY `session` (`session`)
) ENGINE=MyISAM AUTO_INCREMENT=3 DEFAULT CHARSET=utf8
"AUTO_INCREMENT=3" steht hier nur exemplarisch.
Liebe Grüße aus dem schönen Oberharz
Tom vom Berg