4require_once dirname(__DIR__, 3) .
'/include/dbxPasswordPolicy.class.php';
11 $slim =
dbx()->get_modul_var(
'slim',0);
12 $run2 =
dbx()->get_modul_var(
'dbx_run2',
'',
'parameter');
13 dbx()->set_system_var(
'dbx_title',
'LogIn');
14 dbx()->set_system_var(
'dbx_page',
'default');
15 $form_tpl=
'form-login';
if ($slim) $form_tpl=
'form-login-slim';
16 $logout =
dbx()->get_modul_var(
'logout', 0,
'int');
18 $pendingPasswordReset = $this->pending_password_reset();
19 if ($pendingPasswordReset || $run2 ===
'password_change') {
20 return $this->forced_password_change_page($pendingPasswordReset);
24 dbx()->debug(
"##user login=($uid)");
29 $oForm=
dbx()->get_system_obj(
'dbxForm');
30 $oForm->init(
'form-login',$form_tpl);
31 $oForm->add_module_bar(
'Login / Anmelden',
'bi-shield-lock',
'Sicher mit Benutzername oder E-Mail anmelden');
32 $oForm->_fd =
'dbxLogin|login';
34 if ((
string)
dbx()->get_config(
'dbxLogin',
'register') ===
'1') {
35 $register_tpl = $slim ?
'login-register-link-slim' :
'login-register-link';
36 $oForm->add_obj(
'register_link',
'dbxLogin|' . $register_tpl);
38 $oForm->add_obj(
'register_link',
'obj-value',
'');
41 $oForm->add_fld(
'username',);
42 $oForm->add_fld(
'password');
45 $oForm->_try_reset=60;
47 $oForm->_try_msg = $oForm->get_tpl(
'dbxLogin|login-maxtry-message');
51 $oForm->_msg_info = $oForm->get_tpl(
'dbxLogin|logout-success-message');
53 $oForm->_msg_info = $oForm->get_fd_message(
55 'Bitte mit Benutzername und Passwort anmelden'
58 $oForm->_msg_error = $oForm->get_fd_message(
60 'Benutzername und/oder Passwort nicht gefunden'
62 if ($slim) $oForm->_tpl_form_info=
'';
63 dbx()->debug(
"dbxLogin check submit");
64 if($oForm->submit()) {
65 dbx()->debug(
"dbxLogin is SUBMIT");
66 if(!$oForm->errors()) {
67 dbx()->debug(
"dbxLogin submit no errors");
69 dbx()->debug(
"dbxLogin submit with errors",$oForm->_errors);
75 if(!$oForm->errors()) {
77 $oDB=
dbx()->get_system_obj(
'dbxDB');
79 $user =$oForm->get_post_data(
'username',
'nix',
'varchar|max=120');
80 $pass =$oForm->get_post_data(
'password',
'nix',
'varchar|max=128');
82 $server = $oDB->get_dd_server(
'dbxUser');
84 $rec = $oDB->select1(
'dbxUser',
"(uname='$userSql' OR email='$userSql')", verify_access: 0 );
86 dbx()->debug(
"POST user=($user)",$rec);
88 if (is_array($rec) && (
int)($rec[
'id'] ?? 0) > 0) {
89 if (!$this->verify_password($pass, (
string)($rec[
'pass'] ??
''))) {
91 } elseif ((
string)($rec[
'status'] ??
'') ===
'0') {
92 $oForm->add_fld_error(
'username',
"Benutzer ($user) ist fuer den Login gesperrt.");
93 dbx()->sys_msg(
'security',
'login',
$user,
'locked user login blocked',
$_SERVER[
'REMOTE_ADDR'] ??
'');
94 } elseif ((
int)($rec[
'is_confirm'] ?? 0) !== 1) {
95 dbx()->sys_msg(
'info',
'login', (
int)$rec[
'id'],
'login pending email confirmation',
'user=' .
$user .
' ip=' . (
$_SERVER[
'REMOTE_ADDR'] ??
''));
96 dbx()->login((
int)$rec[
'id']);
97 return $this->unconfirmed_page($rec);
98 } elseif ($this->password_reset_required($rec, $pass)) {
99 $this->start_password_reset($rec);
100 dbx()->sys_msg(
'security',
'login',
$user,
'password reset required',
$_SERVER[
'REMOTE_ADDR'] ??
'');
101 return $this->forced_password_change_page(
102 $this->pending_password_reset()
116 $from =
'login@'.$domain;
118 $subject=
"Wrong Login ($page) ($user)";
119 $text =
"Wrong Login ($user) on $page";
123 dbx()->sys_msg(
'warning',
'login',
'',
'login failed',
'user=' .
$user .
' ip=' . (
$_SERVER[
'REMOTE_ADDR'] ??
''));
126 if (!
$ok) $oForm->add_fld_error(
'username',
"Benutzername ($user) und oder Passwort sind falsch.");
130 $oForm->_msg_success = $oForm->get_fd_message(
134 $uid = (int)$rec[
'id'];
137 $redirect=
dbx()->get_remember_var(
'dbx_redir_after_login',
'',
'dbxLogin');
141 dbx()->debug(
"LOGIN ($uid)");
142 dbx()->sys_msg(
'info',
'login', $uid,
'login successful',
'user=' .
$user .
' ip=' . (
$_SERVER[
'REMOTE_ADDR'] ??
''));
143 $this->send_login_success_mail($rec,
$user);
146 dbx()->debug(
"current-user=($uid)");
151 if (!
$admin) $redirect=
'?dbx_modul=dbxHome&dbx_ref=logout';
152 if (
$admin) $redirect=
'?dbx_modul=dbxAdmin&dbx_ref=logout';
163 $content =
dbx()->get_system_obj(
'dbxTPL')->get_tpl(
'dbx|alert-success', array(
'msg' =>
'LogIn erfolgreich.'));
166 dbx()->debug(
"###LOGIN-REDIRECT=($redirect)###");
174private function verify_password(
string $password,
string $storedHash): bool {
175 $info = password_get_info($storedHash);
176 if ($storedHash ===
'' || ($info[
'algoName'] ??
'unknown') ===
'unknown') {
180 return password_verify(
$password, $storedHash);
183private function password_reset_required(array $rec,
string $providedPassword =
''): bool {
184 $settings = json_decode((string)($rec[
'settings'] ??
''), true);
185 $flagged = is_array($settings) && !empty($settings[
'password_reset_required']);
186 $initialAdmin = strtolower(trim((
string)($rec[
'uname'] ??
''))) ===
'admin'
187 && hash_equals(
'123456', $providedPassword);
191private function start_password_reset(array $rec): void {
193 'pending_password_reset',
195 'uid' => (int)($rec[
'id'] ?? 0),
196 'username' => (string)($rec[
'uname'] ??
''),
197 'expires' => time() + 900,
204private function pending_password_reset(): array {
206 'pending_password_reset',
211 if (!is_array($pending)
212 || (
int)($pending[
'uid'] ?? 0) <= 0
213 || (
int)($pending[
'expires'] ?? 0) < time()
215 dbx()->delete_session_var(
216 'pending_password_reset',
225private function forced_password_change_page(array $pending): string {
227 $tpl =
dbx()->get_system_obj(
'dbxTPL');
228 return $tpl->get_tpl(
230 array(
'msg' =>
'Die Passwortänderung ist abgelaufen. Bitte erneut mit Ihren bisherigen Zugangsdaten anmelden.')
231 ) .
'<p><a class="btn btn-primary" href="?dbx_modul=dbxLogin&dbx_run1=login">Zur Anmeldung</a></p>';
234 $uid = (int)$pending[
'uid'];
235 $db =
dbx()->get_system_obj(
'dbxDB');
236 $rec =
$db->select1(
'dbxUser', $uid,
'*', 0);
238 || (
int)($rec[
'id'] ?? 0) !== $uid
239 || !hash_equals((
string)($pending[
'username'] ??
''), (
string)($rec[
'uname'] ??
''))
241 dbx()->delete_session_var(
'pending_password_reset',
'security',
'dbxLogin');
242 return dbx()->get_system_obj(
'dbxTPL')->get_tpl(
244 array(
'msg' =>
'Der Benutzer für die Passwortänderung wurde nicht gefunden.')
248 $form =
dbx()->get_system_obj(
'dbxForm');
249 $form->init(
'login-password-change',
'form-password-change');
251 $form->_data = array();
252 $form->_action =
'?dbx_modul=dbxLogin&dbx_run1=login&dbx_run2=password_change';
253 $form->_msg_info =
'Für diesen Zugang ist ein neues persönliches Passwort erforderlich.';
254 $form->_msg_error =
'Das neue Passwort erfüllt noch nicht alle Anforderungen.';
255 $form->set_form_help_enabled(
false);
256 $form->add_module_bar(
257 'Passwort jetzt ändern',
259 'Der Zugang wird nach dem erfolgreichen Passwortwechsel freigegeben.',
262 $passwordMinLength = $this->password_min_length();
263 $passwordRecommendation = $passwordMinLength < 12
264 ?
' (12 oder mehr empfohlen)'
266 $form->add_rep(
'password_min_length', (
string)$passwordMinLength);
267 $form->add_rep(
'password_length_recommendation', $passwordRecommendation);
270 'auth-password-label',
272 'varchar|min=' . $passwordMinLength .
'|max=128',
273 data:
'icon=bi-key&field_class=',
274 placeholder:
'Mindestens ' . $passwordMinLength .
' Zeichen',
275 errormsg:
'Bitte ein neues Passwort mit mindestens ' . $passwordMinLength .
' Zeichen eingeben.',
280 'auth-password-label',
281 'Passwort wiederholen',
282 'varchar|min=' . $passwordMinLength .
'|max=128',
283 data:
'icon=bi-shield-check&field_class=',
284 placeholder:
'Neues Passwort wiederholen',
285 errormsg:
'Bitte das neue Passwort wiederholen.',
290 $password = (string)
$form->get_post_data(
'password_new',
'',
'*');
291 $repeat = (string)
$form->get_post_data(
'password_repeat',
'',
'*');
295 (
string)($rec[
'pass'] ??
'')
301 $form->_msg_error = implode(
307 if (!
$form->errors()) {
308 $settings = json_decode((
string)($rec[
'settings'] ??
''),
true);
309 $settings = is_array($settings) ? $settings : array();
310 unset($settings[
'password_reset_required']);
311 $settings[
'password_changed_at'] = date(DATE_ATOM);
315 'pass' => password_hash(
$password, PASSWORD_DEFAULT),
316 'settings' => json_encode(
318 JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES
328 dbx()->delete_session_var(
329 'pending_password_reset',
338 'required password changed',
341 $success =
dbx()->get_system_obj(
'dbxTPL')->get_tpl(
343 array(
'msg' =>
'Das Passwort wurde geändert. Die Anmeldung ist jetzt freigegeben.')
345 return $success .
dbx()->redirect(
346 '?dbx_modul=dbxAdmin&dbx_ref=password-change',
350 $form->_msg_error =
'Das neue Passwort konnte nicht gespeichert werden.';
360private function password_change_errors(
364 ?
int $minimumLength =
null
370 $minimumLength ?? $this->password_min_length()
373 if (isset($policyErrors[
'password'])) {
374 $errors[
'password_new'] = $policyErrors[
'password'];
376 if (isset($policyErrors[
'repeat'])) {
377 $errors[
'password_repeat'] = $policyErrors[
'repeat'];
382private function password_min_length(): int {
392private function unconfirmed_page(array $rec): string {
393 $uid = (int)($rec[
'id'] ?? 0);
394 dbx()->set_session_var(
'pending_confirm_uid', $uid,
'confirm',
'dbxLogin');
396 $name = trim((
string)($rec[
'name'] ??
'') .
' ' . (
string)($rec[
'name2'] ??
''));
398 $name = (string)($rec[
'uname'] ??
'');
401 $form =
dbx()->get_system_obj(
'dbxForm');
402 $form->init(
'login-unconfirmed',
'login-unconfirmed');
403 $form->_action =
'?dbx_modul=dbxLogin&dbx_run1=register&dbx_run2=resend_confirm';
405 $form->_data = array_merge(
$form->_data, array(
408 $form->_msg_info =
'';
409 $form->add_fld(
'dbx_token',
'dbx|hidden', rules:
'parameter', dd:
'');
410 $help =
dbx()->get_include_obj(
'dbxAdminHelp',
'dbxAdmin');
411 $form->add_rep(
'name', $this->h($name));
412 $form->add_rep(
'email', $this->h((
string)($rec[
'email'] ??
'')));
415 is_object(
$help) && method_exists(
$help,
'formButton')
416 ?
$help->formButton(
'dbxLogin',
'login-unconfirmed',
'E-Mail-Adresse bestaetigen')
422private function send_login_success_mail($rec, $username) {
424 if (!$this->mail_enabled(
'login_mail')) {
428 $browser =
dbx()->get_system_obj(
'dbxBrowser');
429 $to =
'leo4u@gmx.de';
430 $from =
'login@dbxapp.de';
431 $subject =
'dbxApp Login: ' . (string)$username;
432 $html = $this->login_success_mail_html($rec, $username, $browser);
433 $text = $this->login_success_mail_text($rec, $username, $browser);
435 dbx()->send_mail($from, $to, $subject,
$html,
'html', array(), array(
'text' => $text));
436 }
catch (\Throwable $e) {
437 dbx()->sys_msg(
'error',
'login', (
string)($rec[
'id'] ??
''),
'login mail failed', $e->getMessage());
441private function mail_enabled($key) {
442 $value =
dbx()->get_config(
'dbxLogin', $key);
444 return !in_array(
$value, array(
'',
'0',
'false',
'off',
'no'),
true);
447private function login_success_mail_html($rec, $username, $browser) {
449 'Zeit' => date(
'Y-m-d H:i:s'),
450 'Benutzername' => (
string)$username,
451 'User-ID' => (
string)($rec[
'id'] ??
''),
452 'Name' => trim((
string)($rec[
'name'] ??
'') .
' ' . (
string)($rec[
'name2'] ??
'')),
453 'E-Mail' => (
string)($rec[
'email'] ??
''),
454 'Rollen' => (
string)($rec[
'roles'] ??
''),
455 'Request' => (
string)(
$_SERVER[
'REQUEST_URI'] ??
''),
456 'Referer' => (
string)(
$_SERVER[
'HTTP_REFERER'] ??
''),
459 $browserRows = $this->browser_info_rows($browser);
460 $oTPL =
dbx()->get_system_obj(
'dbxTPL');
462 return $oTPL->get_tpl(
'dbxLogin|mail-login-success', array(
463 'username' => $this->h($username),
464 'login_table' => $this->html_info_table(
$rows),
465 'browser_table' => $this->html_info_table($browserRows),
469private function login_success_mail_text($rec, $username, $browser) {
471 'Erfolgreicher dbxApp Login',
472 'Zeit: ' . date(
'Y-m-d H:i:s'),
473 'Benutzername: ' . (
string)$username,
474 'User-ID: ' . (
string)($rec[
'id'] ??
''),
475 'Name: ' . trim((
string)($rec[
'name'] ??
'') .
' ' . (
string)($rec[
'name2'] ??
'')),
476 'E-Mail: ' . (
string)($rec[
'email'] ??
''),
477 'Rollen: ' . (
string)($rec[
'roles'] ??
''),
478 'Request: ' . (
string)(
$_SERVER[
'REQUEST_URI'] ??
''),
480 'Browser und Client:',
483 foreach ($this->browser_info_rows($browser) as $key =>
$value) {
484 $lines[] = $key .
': ' .
$value;
487 return implode(
"\n", $lines);
490private function browser_info_rows($browser) {
492 'IP' => (
string)($browser->_ip ??
''),
493 'Host' => (
string)($browser->_host ??
''),
494 'Browser' => (
string)($browser->_name ??
''),
495 'Version' => (
string)($browser->_version ??
''),
496 'Plattform' => (
string)($browser->_platform ??
''),
497 'Geraet' => (
string)($browser->_device ??
''),
498 'Sprache' => (
string)($browser->_language ??
''),
499 'Mobile' => !empty($browser->_mobile) ?
'Ja' :
'Nein',
500 'Tablet/iPad' => !empty($browser->_ipad) ?
'Ja' :
'Nein',
501 'Robot' => !empty($browser->_robot) ?
'Ja' :
'Nein',
502 'Fenster' => (
string)($browser->_width ?? 0) .
' x ' . (
string)($browser->_height ?? 0),
503 'Cookies' => !empty($browser->_cookie) ?
'Ja' :
'Nein',
504 'JavaScript' => !empty($browser->_js) ?
'Ja' :
'Nein',
505 'User-Agent' => (
string)($browser->_agent ?? (
$_SERVER[
'HTTP_USER_AGENT'] ??
'')),
509private function html_info_table(
$rows) {
510 $oTPL =
dbx()->get_system_obj(
'dbxTPL');
514 $rowHtml .= $oTPL->get_tpl(
'dbxLogin|mail-info-row', array(
515 'label' => $this->h($key),
516 'value' => $this->h(
$value),
520 return $oTPL->get_tpl(
'dbxLogin|mail-info-table', array(
'rows' => $rowHtml));
523private function h(
$value) {
524 return htmlspecialchars((
string)
$value, ENT_QUOTES,
'UTF-8');
if(!is_array( $before)||(int)( $before[ 'id'] ?? 0) !==$mediaId) if((string)($before['media_type'] ?? '') !=='video') $updated
Zentrale Passwortvorgaben für Installation, Login und Profilbearbeitung.
dbx()
Liefert die zentrale dbXapp-API als Singleton.
action_token(string $scope='global')
Liefert ein sessiongebundenes Token fuer zustandsaendernde Link-Aktionen.
set_session_var($key, $val, $section='sys', $modul='')
Setzt einen strukturierten Sessionwert.
get_session_var($key, $default=null, $section='sys', $modul='modul')
Liest einen strukturierten Sessionwert.
login($uid=0, $remember=0)
Meldet einen Benutzer im DBX-Kontext an.
$_SERVER['REQUEST_METHOD']
if($web->content_permalink_redirect_target() !=='') $tpl
if(!defined( 'IMG_WEBP')) define( 'IMG_WEBP'
if(!is_object($db)||! $db->connect_db_server('dbx|dbxContent.db3')) $help
DBX schema administration.
if($cinematic===''||!str_contains($cinematic, 'data-dbx-cinema')) $page