Auth
Sitzungs-basierte Authentifizierung, das vordefinierte Anmeldeformular und das Benutzer-Plugin-Muster aus der Produktion.
Nibiru bietet einen auf Sitzungen basierenden Authentifizierungskern (Nibiru\Auth) und ein Modul users, das Ihnen eine funktionierende Anmeldeformular, eine Autorisierung überprüft und das Datenbankschema in drei Befehlen bereitstellt.
Der Auth-Kernpunkte
Abschnitt betitelt „Der Auth-Kernpunkte“Auth::auth($login, $password) ist der niedrigste Funktionsaufruf. Er:
- Sucht den Benutzer nach
user_login. - Entschlüsselt das gespeicherte Passwort mit dem Salt aus
[SECURITY] password_hash. - Bei Übereinstimmung wird
$_SESSIONdurch['auth' => ['session_id' => …, 'user_id' => …, 'login' => …]]ersetzt.
$auth = new \Nibiru\Auth();if ($auth->auth($_POST['login'], $_POST['password'])) { View::forwardTo('/dashboard');} else { View::assign(['error' => 'Invalid credentials.']);}Das Modul Benutzer
Abschnitt betitelt „Das Modul Benutzer“Generieren Sie es einmal mit der Befehlszeilenschnittstelle (CLI):
./nibiru -m usersFühren Sie dann die entsprechenden Migrationen aus:
./nibiru -mi localSie haben jetzt:
application/module/users/— der Modulordner.usersTabelle — erstellt durch005-user.sql.UserPlugin —Nibiru\Module\Users\Plugin\UsermitisAuthorized(),loginForm(),currentUser().
Ein vollständiger Anmeldeprozess
Abschnitt betitelt „Ein vollständiger Anmeldeprozess“application/controller/loginController.php:
<?phpnamespace Nibiru;use Nibiru\Adapter\Controller;use Nibiru\Module\Users\Plugin\User;
class loginController extends Controller{ private User $user;
public function __construct() { parent::__construct(); $this->user = new User(); }
public function pageAction() { if ($this->user->isAuthorized()) { View::forwardTo('/'); return; } View::assign([ 'title' => 'Sign in', 'loginForm' => $this->user->loginForm(), ]); }
public function submitAction() { if ($_SERVER['REQUEST_METHOD'] !== 'POST') return; $auth = new Auth(); if ($auth->auth($_POST['login'] ?? '', $_POST['password'] ?? '')) { View::forwardTo('/'); } else { View::assign(['error' => 'Invalid login.']); } }
public function logoutAction() { unset($_SESSION['auth']); session_regenerate_id(true); View::forwardTo('/login'); }
public function navigationAction() { JsonNavigation::getInstance()->loadJsonNavigationArray(); }}application/view/templates/login.tpl:
{include 'shared/header.tpl'}<body>{include file="navigation.tpl"}<main class="container"> <h1>{$title}</h1> {if $error}<div class="alert alert-danger">{$error}</div>{/if} {$loginForm nofilter}</main>{include 'shared/footer.tpl'}</body>Form::action="/login/submit" wird in loginForm() gesetzt, sodass das Formular an die richtige Aktion gepostet wird.
Schutz von Controllern
Abschnitt betitelt „Schutz von Controllern“Die einfache Überprüfung:
public function pageAction() { if (!$this->user->isAuthorized()) { View::forwardTo('/login'); return; } / ...}Für rollebasierte Überprüfungen verwenden die Showcase-Anwendungen den Acl-Plugin aus dem gleichen Modul:
use Nibiru\Module\Users\Plugin\Acl;
if (!Acl::can('edit', 'documents')) { View::forwardTo('/forbidden'); return;}Tabellen acl, user_to_acl, acl-data (Migrationen 001, 008, 011) bilden die Grundlage für Rollen und Berechtigungen.
Härterung
Abschnitt betitelt „Härterung“Für die Produktion ersetzen Sie Auth::auth() durch eine verstärkte Version:
namespace Nibiru;use Nibiru\Pdo;
class HardenedAuth{ public function auth(string $login, string $password): bool { $row = Pdo::fetchRow( 'SELECT user_id, user_pass FROM "user" WHERE user_login = :l AND user_account_active = 1', [':l' => $login] ); if (!$row || !password_verify($password, $row['user_pass'])) { return false; } if (password_needs_rehash($row['user_pass'], PASSWORD_ARGON2ID)) { Pdo::update('user', [ 'user_pass' => password_hash($password, PASSWORD_ARGON2ID), ], ['user_id' => $row['user_id']]); } session_regenerate_id(true); $_SESSION['auth'] = [ 'session_id' => session_id(), 'user_id' => $row['user_id'], 'login' => $login, ]; return true; }}Migrieren Sie vorhandene Zeilen beim ersten Anmelden mit password_needs_rehash.
Nibiru generiert keine CSRF-Token für Sie. Fügen Sie diese selbst hinzu:
public function pageAction() { if (!isset($_SESSION['csrf'])) { $_SESSION['csrf'] = bin2hex(random_bytes(16)); } View::assign(['csrf' => $_SESSION['csrf']]);}
public function submitAction() { if (!hash_equals($_SESSION['csrf'] ?? '', $_POST['csrf'] ?? '')) { http_response_code(419); return; } / ...handle submission...}Fügen Sie <input type="hidden" name="csrf" value="{$csrf}"> in Ihr Formular ein.
QR-Code-Anmeldung (TPMS-Muster)
Abschnitt betitelt „QR-Code-Anmeldung (TPMS-Muster)“Produktionsanwendungen umfassen eine QR-codes-basierte Magics-Link-Anmeldung, die kurzlebige Token ausgibt. Der Ablauf:
- Der Benutzer scannen einen QR-Code → Die URL lautet
/login/token/<one-time-token>. tokenActionvalidiert und erstellt eine Sitzung.
Das Framework hängt bereits von bacon/bacon-qr-code und picqer/php-barcode-generator über Composer ab, sodass Sie QR-Codes direkt rendern können:
$writer = new \BaconQrCode\Writer(new \BaconQrCode\Renderer\ImageRenderer( new \BaconQrCode\Renderer\RendererStyle\RendererStyle(220), new \BaconQrCode\Renderer\Image\SvgImageBackEnd()));$svg = $writer->writeString('https://app.example.com/login/token/' . $token);View::assign(['qr' => $svg]);Häufige Fallen
Abschnitt betitelt „Häufige Fallen“$_SESSIONwird nicht zusammengeführt, sondern ersetzt durch die StandardmethodeAuth::auth(). Alles, was Sie vor dem Login gespeichert hatten, geht verloren. Speichern und wiederherstellen Sie explizit, wenn dies erforderlich ist.- Keine Rate Limiting. Fügen Sie Fail2Ban oder einen middleware-artigen Beobachter hinzu.
- Sitzungs-Cookies benötigen Flags. Setzen Sie
session.cookie_secure = 1,session.cookie_httponly = 1undsession.cookie_samesite = "Lax"in der php.ini für die Produktion.