認証
セッションベースの認証、事前構築されたログインフォーム、およびプロダクションからのユーザープラグインパターン。
Nibiru はセッションベースの認証コア (Nibiru\Auth) と users モジュールを搭載しており、3つのコマンドで動作するログインフォーム、権限チェック、データベーススキーマを提供します。
Auth::auth($login, $password) は最下層の呼び出しです。このメソッドは:
user_loginでユーザーを検索します。[SECURITY] password_hashから取得したソルトを使用して、保存されたパスワードを復号化します。- マッチする場合、
$_SESSIONを['auth' => ['session_id' => …, 'user_id' => …, 'login' => …]]に置き換えます。
$auth = new \Nibiru\Auth();if ($auth->auth($_POST['login'], $_POST['password'])) { View::forwardTo('/dashboard');} else { View::assign(['error' => 'Invalid credentials.']);}ユーザーモジュール
Section titled “ユーザーモジュール”CLIで一度生成します:
./nibiru -m usersその後、対応するマイグレーションを実行します。
./nibiru -mi localあなたには以下があります:
application/module/users/— モジュールフォルダ。usersテーブル —005-user.sqlによって作成されました。Userプラグイン —Nibiru\Module\Users\Plugin\UserでisAuthorized(),loginForm(),currentUser()があります。
完全なログインフロー
Section titled “完全なログインフロー”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" は loginForm() 内で設定されているため、フォームは正しいアクションに投稿されます。
コントローラーの保護
Section titled “コントローラーの保護”単純なチェック:
public function pageAction() { if (!$this->user->isAuthorized()) { View::forwardTo('/login'); return; } / ...}ロール認識のチェックのために、デモンストレーションアプリケーションは同じモジュールから Acl プラグインを使用しています。
use Nibiru\Module\Users\Plugin\Acl;
if (!Acl::can('edit', 'documents')) { View::forwardTo('/forbidden'); return;}テーブル acl, user_to_acl, acl-data(マイグレーション 001, 008, 011)が役割/権限の基盤を形成しています。
本番環境では、Auth::auth() を強化されたバージョンに置き換えてください。
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; }}既存の行を最初のログイン時に password_needs_rehash で移行します。
NibiruはCSRFトークンを生成しません。自分で追加してください:
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...}フォームに <input type="hidden" name="csrf" value="{$csrf}"> を埋め込んでください。
QRコードログイン(TPMSパターン)
Section titled “QRコードログイン(TPMSパターン)”生産アプリケーションには、QRコードベースのマジックリンクログインが含まれています。このフローは以下の通りです:
- ユーザーがQRコードをスキャン → URLは
/login/token/<one-time-token>です。 tokenActionはトークンを検証し、セッションを作成します。
フレームワークはすでに bacon/bacon-qr-code と picqer/php-barcode-generator を Composer 経由で依存しているため、QR コードをインラインでレンダリングできます:
$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]);一般的な落とし穴
Section titled “一般的な落とし穴”$_SESSIONは置き換えられ、マージされません。デフォルトのAuth::auth()によって。ログイン前に保存したものは失われます。必要に応じて明示的に保存と復元してください。- レート制限はありません。Fail2Ban またはミドルウェアスタイルの観察者を追加してください。
- セッションクッキーにはフラグが必要です。php.ini の
session.cookie_secure = 1、session.cookie_httponly = 1、およびsession.cookie_samesite = "Lax"を本番環境で設定してください。