Wie man eine REST API mit Symfony und JWT-Authentifizierung aufbaut

In diesem Tutorial zeige ich dir Schritt für Schritt, wie du eine REST API mit dem Symfony Framework erstellst. Diese API wird durch ein Token-basiertes Authentifizierungssystem abgesichert, sodass nur autorisierte Benutzer darauf zugreifen können.

Voraussetzungen

  • Grundkenntnisse in PHP und Composer.
  • PHP 8.2 oder höher.
  • Composer (der PHP-Paketmanager).
  • Ein grundlegendes Verständnis von Symfony und RESTful APIs ist von Vorteil, aber nicht zwingend notwendig.

1. Symfony installieren

Zuerst müssen wir Symfony installieren. Öffne dein Terminal und führe folgenden Befehl aus:

composer create-project symfony/skeleton my_rest_api

Dieser Befehl erstellt ein neues Symfony-Projekt in einem Ordner namens my_rest_api. Der Symfony-Skeleton ist ein minimales Grundgerüst, ideal für den Aufbau einer API.

Wechsle in dein neu erstelltes Projektverzeichnis:

cd my_rest_api

2. API-Bundle installieren

Das API Platform Bundle von Symfony erleichtert es, APIs zu erstellen. Um es zu installieren, führen wir den folgenden Befehl aus:

composer require api

Dadurch wird die API Platform in deinem Symfony-Projekt aktiviert. Mit diesem Bundle hast du bereits viele hilfreiche Funktionen, wie automatische Dokumentation. (Hinweis: Docker kannst du je nach belieben installieren oder weglassen. Ich gehe erstmal nicht weiter auf Docker in diesem Tutorial ein.)

3. Ein Datenbankmodell erstellen

Wir erstellen nun eine einfache Entity, um unsere API aufzubauen. Eine Entity ist im Wesentlichen eine Klasse, die in der Datenbank gespeichert wird.

Zuerst müssen wir sicherstellen, dass du eine Datenbank konfiguriert hast. Dupliziere hierzu die .env Datei und benenne diese wie folgt .env.local – hinterlege deine Datenbank Einstellungen:

DATABASE_URL="mysql://db_user:db_password@127.0.0.1:3306/db_name?serverVersion=8&charset=utf8mb4"

Erstelle die Datenbank mit:

php bin/console doctrine:database:create

Um eine Entity zu erstellen, verwenden wir im Anschluss den Befehl folgende zwei Befehle:

composer require symfony/maker-bundle --dev
php bin/console make:entity

Nennen wir die Entity zum Beispiel Product. Du wirst nun gefragt, welche Felder die Entity haben soll. Fügen wir zwei einfache Felder hinzu:

  • name (string)
  • price (float)

Jetzt wird die Datei src/Entity/Product.php generiert.

Damit die Entity in der Datenbank angelegt wird, führen wir folgende Befehle aus:

php bin/console make:migration
php bin/console doctrine:migrations:migrate

Der erste Befehl erstellt die Datenbank, der zweite erstellt eine Migrationsdatei, und der letzte führt diese Migration aus, um die Tabelle in der Datenbank anzulegen.

4. Die API-Ressource freigeben

Jetzt machen wir diese Product-Entity über unsere API zugänglich. Dafür markieren wir die Product-Entity als API-Resource, indem wir die folgende Annotation hinzufügen:

// src/Entity/Product.php
use App\Repository\ProductRepository;
use Doctrine\ORM\Mapping as ORM;
use ApiPlatform\Metadata\ApiResource;

#[ApiResource]
#[ORM\Entity(repositoryClass: ProductRepository::class)]
class Product
{
    // ...
}

API Platform wird automatisch CRUD-Operationen (Create, Read, Update, Delete) für diese Ressource freigeben. Wenn du nun http://localhost/my_rest_api/public/index.php/api besuchst, siehst du die neue Ressource Product.

5. Authentifizierung mit JWT einrichten

Nun sichern wir die API mit JWT ab, sodass nur authentifizierte Benutzer Zugriff haben. Dazu verwenden wir das LexikJWTAuthenticationBundle. Installiere es mit folgendem Befehl:

composer require lexik/jwt-authentication-bundle:^2.19

Dieses Bundle hilft uns dabei, JSON Web Tokens zu generieren und zu validieren.

a) Konfiguration des JWT-Bundles

Wir müssen nun einige Schritte durchführen, um JWT korrekt zu konfigurieren. Zuerst generieren wir ein Schlüsselpaar für die Token-Signierung:

php bin/console lexik:jwt:generate-keypair

Dies erstellt zwei Dateien (private.pem und public.pem), die für die Signierung und Validierung der JWTs verwendet werden.

Jetzt müssen wir das Security-System von Symfony konfigurieren. Öffne die Datei config/packages/security.yaml und füge den folgenden Code hinzu:

security:
    encoders:
        Symfony\Component\Security\Core\User\UserInterface:
            algorithm: auto

    providers:
        app_user_provider:
            entity:
                class: App\Entity\User
                property: email

    firewalls:
        login:
            pattern:  ^/api/login
            stateless: true
            json_login:
                check_path: /api/login
                username_path: email
                password_path: password

        api:
            pattern:   ^/api
            stateless: true
            jwt: ~
            provider: app_user_provider

    access_control:
        - { path: ^/api/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/api,       roles: IS_AUTHENTICATED_FULLY }

b) Ein User-Entity erstellen

Wir benötigen eine User-Entity, um Benutzer zu verwalten. Erstelle diese Entity mit folgendem Befehl:

php bin/console make:user

Folge den Anweisungen und füge Felder wie email und password hinzu. Anschließend führe die Migrationsschritte durch, um die User-Tabelle zu erstellen:

php bin/console make:migration
php bin/console doctrine:migrations:migrate

6. Registrierung und Login einrichten

a) Registrierung

Erstelle einen Controller für die Registrierung:

php bin/console make:controller RegistrationController

Füge in der RegistrationController.php eine Methode hinzu, um neue Benutzer zu registrieren:

// src/Controller/RegistrationController.php
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
use App\Entity\User;

class RegistrationController
{
    #[Route('/api/register', methods: ['POST'])]
    public function register(Request $request, UserPasswordEncoderInterface $passwordEncoder): Response
    {
        $data = json_decode($request->getContent(), true);

        $user = new User();
        $user->setEmail($data['email']);
        $user->setPassword($passwordEncoder->encodePassword($user, $data['password']));

        // Speichere den Benutzer in der Datenbank...

        return new Response('User registered successfully!', Response::HTTP_CREATED);
    }
}

b) Login

Der Login wird über die in security.yaml konfigurierte Route /api/login abgewickelt. Um dich anzumelden, sende eine POST-Anfrage mit den Anmeldedaten (email, password) an diese Route, und bei Erfolg erhältst du ein JWT-Token zurück.

7. API-Zugriff testen

Jetzt kannst du deine API mit einem Tool wie Postman, SOAP Ui oder cURL testen. Sende eine POST-Anfrage an /api/login mit den Benutzerdaten, und du erhältst ein JWT-Token zurück, das du in den folgenden Anfragen als Authorization-Header senden musst:

Authorization: Bearer <dein_token>

Fazit

Herzlichen Glückwunsch! Du hast eine funktionierende REST API mit Symfony erstellt und die Authentifizierung über JWT integriert. Von hier aus kannst du die API weiter ausbauen, zusätzliche Ressourcen hinzufügen oder tiefer in Symfony und die API Platform eintauchen.

* Werbung/Affiliate Link
Das weltweit erste 2400W All-in-One Balkonkraftwerk mit Speicher für dein Zuhause

Schreibe einen Kommentar

Erforderliche Felder sind entsprechend markiert.

Wird nicht veröffentlicht.