Osumi Framework
es en eu v9.12.1 GitHub

Autentifikazioa — Errezetak eta praktika onak

Osumi Framework 9.10-en autentifikazioa normalean honako hauekin eraikitzen da:


1. Ibilbideak Middleware bidez babestea

Adibidea:

ORoute::get(
	'/profile',
	ProfileComponent::class,
	[
		OMiddleware::PHASE_BEFORE => [
			LoginMiddleware::class
		]
	]
);

Ibilbidea bat datorrenean:

  1. before Middlewareak exekutatzen dira.
  2. LoginMiddleware-k eskaera baliozkotzen du.
  3. stop => true itzultzen badu, gainerako before Middlewareak eta osagaia ez dira exekutatzen.
  4. afterResponse exekutatzen jarraitzen da.
  5. Framework-ak errore-erantzun tipatua bidaltzen du.

Autentifikazio-hutsegiteek normalean HTTP 401 erabili behar dute.


2. Login Middleware

Login Middleware batek konfiantzazko testuingurua argitaratu behar du baliozkotzea zuzena denean.

<?php

declare(strict_types=1);

namespace Osumi\OsumiFramework\App\Middleware;

use Osumi\OsumiFramework\Core\OMiddleware;

final class LoginMiddleware {
	/**
	 * Validate authentication and publish user context.
	 *
	 * @param string $phase Current middleware phase.
	 * @param array<string, mixed> $data Current middleware pipeline data.
	 *
	 * @return array<string, mixed> Middleware result.
	 */
	public static function handle(
		string $phase,
		array $data
	): array {
		if ($phase !== OMiddleware::PHASE_BEFORE) {
			return [];
		}

		// Authorization tokena hemen baliozkotu.

		$is_valid = true;
		$id_user = 42;
		$role = 'admin';

		if (!$is_valid) {
			return [
				'stop' => true,
				'status_code' => 401,
				'message' => 'Unauthorized'
			];
		}

		return [
			'context' => [
				'id' => $id_user,
				'role' => $role
			]
		];
	}
}

LoginMiddleware publikoki Login gisa azaltzen da.


3. Login amaiera-puntua sortzea

Login amaiera-puntu batek normalean:

  1. Kredentzialak DTO baten bidez jasotzen ditu.
  2. Zerbitzu baten bidez baliozkotzen ditu.
  3. Token bat sortzen du.
  4. Tokena bezeroari itzultzen dio.
  5. Bezeroak tokena Authorization bidez bidaltzen du.

DTO adibidea:

class LoginDTO extends ODTO {
	#[ODTOField(required: true)]
	public ?string $email = null;

	#[ODTOField(required: true)]
	public ?string $password = null;
}

Autentifikazio-zerbitzua:

class AuthService extends OService {
	/**
	 * Validate credentials and return a token.
	 *
	 * @param string $email User email.
	 * @param string $password Plain-text password.
	 *
	 * @return array{token: string}|null Token data or null on failure.
	 */
	public function login(
		string $email,
		string $password
	): ?array {
		$user = User::findOne([
			'email' => $email
		]);

		if (
			$user === null ||
			!password_verify(
				$password,
				$user->password
			)
		) {
			return null;
		}

		$token = new OToken(
			$this->getConfig()->getExtra('secret')
		);

		$token->addParam(
			'id',
			$user->id
		);

		return [
			'token' => $token->getToken()
		];
	}
}

4. Middleware testuingurua osagaietan irakurtzea

Testuinguru osoa lortzeko:

$login = $req->getMiddleware(
	'Login'
);

Balio bakarra lortzeko:

$id_user = $req->getMiddlewareValue(
	'Login',
	'id'
);

Balio bakarra behar denean getMiddlewareValue() erabiltzea gomendatzen da.


5. Middleware testuingurua DTOetan erabiltzea

DTOek Middleware testuingurua iturburu esplizitu gisa erabil dezakete:

#[ODTOField(
	required: true,
	middleware: 'Login',
	middlewareProperty: 'id'
)]
public ?int $idUser = null;

Horrek bezeroak autentifikatutako erabiltzailearen IDa faltsutzea saihesten du.

Middleware testuinguruko balioa falta bada, DTOaren balioa null izaten jarraitzen du; ez da bezeroaren sarrerara itzultzen.


6. DTO bat erabiltzen duen babestutako amaiera-puntua

Ibilbidea:

ORoute::get(
	'/my-cinemas',
	GetCinemasComponent::class,
	[
		OMiddleware::PHASE_BEFORE => [
			LoginMiddleware::class
		]
	]
);

DTOa:

class GetCinemasDTO extends ODTO {
	#[ODTOField(
		required: true,
		middleware: 'Login',
		middlewareProperty: 'id'
	)]
	public ?int $idUser = null;
}

Osagaia:

class GetCinemasComponent extends OComponent {
	private ?CinemaService $cinema_service = null;

	/**
	 * Prepare the component.
	 */
	public function __construct() {
		parent::__construct();

		$this->cinema_service = inject(
			CinemaService::class
		);
	}

	/**
	 * Load cinemas for the authenticated user.
	 *
	 * @param GetCinemasDTO $dto Authenticated request DTO.
	 *
	 * @return void
	 */
	public function run(GetCinemasDTO $dto): void {
		if (
			!$dto->isValid() ||
			$dto->idUser === null
		) {
			return;
		}

		$this->list = $this->cinema_service->getCinemas(
			$dto->idUser
		);
	}
}

7. Baimenak

Middleware batek rol edo baimen-informazioa argitara dezake:

return [
	'context' => [
		'id' => 42,
		'role' => 'admin'
	]
];

Osagai batek informazio hori kontsulta dezake:

$role = $req->getMiddlewareValue(
	'Login',
	'role'
);

Ibilbide askok partekatzen dituzten baimen-arauetarako, hobe da baimenetarako Middleware bereizi bat erabiltzea osagaietan egiaztapenak errepikatzea baino.


8. Saioa ixtea

Tokenetan oinarritutako autentifikazio stateless batean, saioa ixtea normalean bezeroan tokena ezabatzea da.

Zerbitzarian baliogabetzea behar bada, gorde baliogabetutako token-identifikatzaileak zerbitzu edo cache batean eta egin autentifikazio Middlewareak horiek baztertzea.


9. Praktika onak


10. Laburpena

Ohiko autentifikazio-fluxu batek honako hauek ditu:

  1. Login amaiera-puntua.
  2. Tokenak sortzen dituen zerbitzua.
  3. LoginMiddleware babestutako ibilbideetan.
  4. Konfiantzazko Middleware testuingurua.
  5. Testuinguru hori erabiltzen duten DTOak eta/edo ORequest.
  6. Negozio-logika duten zerbitzuak.

Hau da ordezko kanonikoa, 9.9 bertsioan sartutakoa, Filters zaharretan oinarritutako autentifikazio-fluxuarentzat.