1. 2024-09-13 http-Filter
-
Ein Filter kann den Request überprüfen bzw den Response ändern
-
in der Cloud können wir keine Cookies verwenden, da diese am Client liegen. Der Server muss immer in der DB nachschauen (oder der Client müsste immer zum selben Server groutet werden) → das wäre zu langsam.
-
Sticky Session sind nicht optimal, da der LoadBalancer den Client immer zum selben Pod schicken würde.
-
Lösungen wie Keycloak verwenden trotzdem Cookies (ist performancemäßig egal, da man sich eh nicht so oft authentifiziert → ebenfalls DB-Zugriff)
-
2. 2024-09-20
2.1. container request filter
-
Prüft, ob im Header die Authentifizierung (wer bin ich) passt.
…
Problem:
-
Die zwei Filter sind unabhängig
-
Wir müssen jedoch username und password vom Authentication Filter zum Authorization Filter übergeben
-
Dazu verwenden wir den ContainerRequestContext
HÜ:
-
Unit-Tests erstellen mit rest-assured
-
beim Login Session in DB erstellen (Cookies in DB speichern)
-
wir verwenden als DB H2
4. Aufgabenstellung
-
ein User-Tabelle wird erstellt (Password hashen und salten) und auch Session-Tabelle
-
eigene Annotation @AllowAll wird erstellt
-
Ablauf
-
nach Überprüfen des Usernames und Password wird eine Session in die DB eingetragen mit FK auf User
-
die Session erhält eine UUID und einen Zeitstempel (Gültigkeit zB 1h)
-
die Session wird nun mit Set-Cookie an den Browser gesendet
-
die Browser senden nun dieses Cookie bei jedem Request an den Endpoint zurück
-
im Authentication-Filter (wer bin ich) wird aus dem Cookie der User durch DB-Zugriff festgestellt.
-
-
HÜ
-
Was haben wir bisher:
-
Wir haben einen Login-Request mit AllowAll
-
Alles wird durchgelassen, es wird in der Datenbank eine Session erstellt.
-
Als Response des Login-Requests wird ein Cookie dem Browser übergeben
-
Bei jeden (hello-) Request wird ein Cookie mitgesendet.
-
-
Was ist zu tun?
-
Bei jedem neuen Request wird aus der Session Tabelle der User herausgeholt (Wer bin ich - Filter)
-
Diese User-Credentials werden in den Context-Properties gespeichert.
-
Im Was darf ich - Filter wird für jeden Endpoint kontrolliert, ob eine User Id vorhanden ist
-
-
Kommende Woche
-
@RolesAllowed
-
Rollenkonzept einführen
-
-
6. @Produces von CDI
-
Eine Objekt wird beim @Inject nicht vom Container instanziert, sondern meine Funktion mit "new" wird verwendet
7. 2024-10-04



7.1. JWT
-
Bislang haben wir Cookies verwendet.
-
Nachteil: Bei jedem Request erfolgt ein Datenbankzugriff
-
Abhilfe> Sticky Session
-
Ein User wird immer mit dem ersten Server verbunden, mit dem er Kontakt hatte (Lastverteilung)
-
Auf diesem Server werden die Cookies auf das File System (oder lokale DB) geschrieben
-
Dieses Verfahren ist daher nicht optimal
-
Abhilfe: JWT
-
-
Rolle: Gruppierung von Rechten
-
Usergroup: Gruppierung von Usern

7.2. MOB-Programming
-
alle - ausser dem Driver - schließen den Laptop
-
Navigator: hört sich an, was der Mob ansagt und filtert das richtige raus und diktiert dem Driver
-
Driver: tippt den Code
-
nach ca. 15 min wird gewechselt
7.3. git-secret
❯ gpg --list-keys [keyboxd] --------- pub ed25519 2024-03-15 [SC] 14705EAD108F834E310178E5191650E41055DC8E uid [ultimate] Thomas W. Stütz <t.stuetz@htl-leonding.ac.at> sub cv25519 2024-03-15 [E] ❯ gpg --armor --export t.stuetz@htl-leonding.ac.at -----BEGIN PGP PUBLIC KEY BLOCK----- mDMEZfQUoxYJKwYBBAHaRw8BAQdAZlX/fAe4TuqQeJbl1lBcM8ZxBVR10SZSiJoe /yPaBim0LlRob21hcyBXLiBTdMO8dHogPHQuc3R1ZXR6QGh0bC1sZW9uZGluZy5h Yy5hdD6IkwQTFgoAOxYhBBRwXq0Qj4NOMQF45RkWUOQQVdyOBQJl9BSjAhsDBQsJ CAcCAiICBhUKCQgLAgQWAgMBAh4HAheAAAoJEBkWUOQQVdyOLYMBAPIZgbyPEcnI 03mKahdjEAi+UF8FPPB9ECMMoOHyCXJpAQD4TwenokZmZDuh75NATqLVOKLyG0yV 0hdHefQCx0oRDLg4BGX0FKMSCisGAQQBl1UBBQEBB0DJuoCXAZ3pytv+xKhN4yHm JoicXGuDwa8SHc1x7uOAMgMBCAeIeAQYFgoAIBYhBBRwXq0Qj4NOMQF45RkWUOQQ VdyOBQJl9BSjAhsMAAoJEBkWUOQQVdyOKXgBANHbZH3n/3UxyLXulvWk95jS7Yc6 JH6odqFX9xlwIteYAQCpy+sU3bh2kdbjMb6Q1Td4F1zoSsav+lB+ZPENjRlnDw== =wAG -----END PGP PUBLIC KEY BLOCK-----
gpg --import public_key.txt
8. 2024-11-08
8.2. Security
8.2.2. Bsp 2: Authorization mit Annotations
-
Problem: Man braucht public-Ressourcen um einen Anlaufpunkt fürs Anmelden zu haben bzw als Frontpage
-
Wir möchten mit Annotations arbeiten, um bei Ressourcen zB @AllowAll darüberschreiben zu können
-
Es werden Annotations eingeführt
-
Erstellen einer Annotation @AllowAll
package at.htl.auth;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface AllowAll {
}
-
Im authenticationFilter wird überprüft, ob AllowAll. Sicherlich besser in AuthorizationFilter
8.2.3. Bsp 3: Login in Session speichern
* Übung ** Richtigstellen: Überprüfung von AllowAll vom AuthenticationFilter zu AuthorizationFilter. Wenn bei Klasse eine strengere Permission steht und bei MEthoden eine @AllowAll, dann gilt immer die freizügigere Permission
-
In LoginResource wird eine Session erstellt (SetCookie)
GET http://localhost:8080/hello
Hello RESTEasy x
-
Problem: Jeder darf auf Resource zugreifen
### POST http://localhost:8080/login Content-Type: application/json { "username": "chris", "password": "password" } > {% client.global.set("cookie", response.headers.valueOf("Set-Cookie")); %} ### GET http://localhost:8080/hello Cookie: {{cookie}} ###
2024-11-08 11:30:19,447 INFO [at.htl.aut.AuthenticationFilter] (executor-thread-1) Session: Session=b3d07c5b-67e8-4813-8591-0dd2efda6dd5
-
Rollen werden erstellt
Nie in die Lebensdauer von JPA-Entities eingreifen
8.3. Exkurs: container managed persistance vs manuelle Transaktionen
zB Gehälter
Transaktion-Begin ... Transaktions-Commit
-
wenn Problem mittendrin, dann sind die ersten Gehälter bereits überwiesen, die späteren sind noch offen
-
daher SET_ROLLBACK_ONLY verwenden
-
Sämtliche Teiltransaktionen werden zurückgerollt
-
10. 2025-02-28 KEycloak
cd compose/keycloak docker build . # wird nicht getagged docker compose --build docker container ls -a docker container ls -aq | xargs docker container rm docker container la -a
-
Empfehlung: Den Realm einmal exportieren und beim Hochfahren automatisch importieren
#!/usr/bin/env bash #/opt/keycloak/bin/kc.sh export --db postgres --db-url-host postgres --db-url-database jdbc:postgresql://postgres/keycloak --db-username keycloak --db-password keycloak --realm demo --dir /opt/keycloak/export /opt/keycloak/bin/kc.sh export --db postgres --db-url jdbc:postgresql://postgres/keycloak \ --db-username keycloak --db-password keycloak \ --realm demo --dir /opt/keycloak/export --users same_file \ --features-disabled=admin-api,admin2
docker compose exec -it keycloak bash docker compose cp ./keycloak/export-realm.sh keycloak:/usr/local/bin docker compose exec -it keycloak bash chmod +x /usr/local/bin/export-realm.sh
#FROM --platform=linux/amd64 quay.io/keycloak/keycloak:26.0 AS builder
FROM quay.io/keycloak/keycloak:26.0 AS builder
# Enable health and metrics support
ENV KC_HEALTH_ENABLED=true
ENV KC_METRICS_ENABLED=true
# Configure a database vendor
ENV KC_DB=postgres
WORKDIR /opt/keycloak
# for demonstration purposes only, please make sure to use proper certificates in production instead
RUN keytool -genkeypair -storepass password -storetype PKCS12 -keyalg RSA -keysize 2048 \
-dname "CN=server" -alias server -ext "SAN:c=DNS:localhost,IP:127.0.0.1" -keystore conf/server.keystore
RUN /opt/keycloak/bin/kc.sh build --health-enabled=true --metrics-enabled=true
#FROM --platform=linux/amd64 quay.io/keycloak/keycloak:26.0
FROM quay.io/keycloak/keycloak:26.0
COPY --from=builder /opt/keycloak/ /opt/keycloak/
COPY ./import/ /opt/keycloak/data/import/
USER root
COPY ./export-realm.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/export-realm.sh
USER keycloak
# change these values to point to a running postgres instance
ENV KC_DB=postgres
ENV KC_DB_URL=keycloak
ENV KC_DB_USERNAME=keycloak
ENV KC_DB_PASSWORD=keycloak
ENV KC_HOSTNAME=localhost
ENTRYPOINT ["/opt/keycloak/bin/kc.sh"]
docker compose exec export-realm.sh
-
1. Varinate zum Sichern
-
Sichern über shell skript
-
Beim Hochfahren mit import-Option restoren.
-
-
2. Variante zum Sichern
-
pgdump der Datenbank
-
Da sind dann auch die Passwörter dabei
-
#!/usr/bin/env bash # to use this script backup container must be running, so start the following before: # docker compose --file backup-keycloak.yaml up set -e mkdir -p ./target docker compose exec postgres pg_dump --dbname=keycloak --username=keycloak | gzip > ./target/keycloak.sql.gz #docker compose cp backup:/export ./target #cp ./target/export/*.json ./keycloak/import
-
keycloak kann auch write-ahead logs (redo-logs in Oracle)
10.1. Keycloak Web-Console
-
Client scopes: Welche Rechte in welchem Kontext (Scope)
-
Read-Scopes: nur GETs, keine POST und PUTs erlaubt
-
Edit-Scope: für POST und PUTs
-
-
Roles: Sammlung von Rechten
-
Groups: Sammlung von Usern
10.1.1. Clients
-
Frontend
-
Varianten
-
Standard-Flow: Browser → Keycloak Plugin kontrolliert JWT ob die benötigte Rolle enthalten ist → wenn nicht (403) wird an den Keycloak weitergeleitet zur Authentifizierung
-
der Keycloak fragt das Backend, ob es erlaubt ist (im Backend gibt es dafür Annotationen zB @RolesAllowed) und gibt ein Token an den Browser zurück
-
Authorization: Der Request wird von einem Authentication & Authorization-Filter (keycloak-plugin) geprüft, ob der User die Rechte hat. Es erfolgt dabei kein Zugriff auf das Backend, da sämtliche Informationen (Policy) im Keycloak enthalten sind.