Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen angezeigt.

Link zu dieser Vergleichsansicht

Beide Seiten der vorigen Revision Vorhergehende Überarbeitung
Nächste Überarbeitung
Vorhergehende Überarbeitung
de:modul:ffit:3-jahr:java:learningunits:lu10:a [2025/11/09 23:21] apeterde:modul:ffit:3-jahr:java:learningunits:lu10:a [2025/11/10 00:02] (aktuell) apeter
Zeile 1: Zeile 1:
 ====== LU10a - Umgang mit Exceptions ====== ====== LU10a - Umgang mit Exceptions ======
 +
 +==== Spring ResponseStatusException ====
 +
 +Allgemein gilt, dass Exceptions in Bezug auf die Performanz schlechter abschneiden als die entsprechenden Checks. Daher sollte man Exceptions nie in "Schönwetter"-Fällen benutzen, sondern höchstens in unerwarteten Situationen. Ein ungültiger API-Aufruf ist in unserem Fall aber unerwartet und kann mittels einer Exception gelöst werden. Werden aber viele ungültige API-Aufrufe erwartet, sollte man eine Exception-freie Alternative in Erwägung ziehen.
 +
 +Spring bietet eine sehr einfache Version, um Fehlerfälle mittels Exceptions abzuhandeln. Dabei wird direkt automatisch eine Antwort mit dem entsprechenden HTTP-Statuscode erstellt und zurückgeschickt.
 +
 +Im nachfolgenden Beispiel wird jeweils ein Project-Objekt geladen und falls kein Objekt in der Datenbank vorhanden ist, wird der Statuscode 404 zurückgegeben. 
 +
 +^ Lange Variante ^ Verkürzte Variante ^ Variante mit Exception ^
 +| <WRAP>
 +<code java>
 +Optional<Project> optionalProject = projectRepository.findById(projectName);
 +if(optionalProject.isEmpty()){
 +    return ResponseEntity.notFound().build();
 +}
 +Project project = optionalProject.get();
 +</code> 
 +</WRAP> | <WRAP>
 +<code java>
 +Project project = projectRepository.findById(projectName).orElse(null);
 +if(null == project){
 +    return ResponseEntity.notFound().build();
 +}
 +</code> 
 +</WRAP> | <WRAP>
 +<code java>
 +Project project = projectRepository.findById(projectName).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "Project not found"));
 +</code>
 +</WRAP> |
 +
 +Ein sehr grosser Vorteil der dritten Variante ist die Wiederverwendbarkeit: Ein ResponseEntity-Objekt kann nur in der API-Methode zurückgegeben werden. Eine ResponseStatusException kann aber auch in einer verschachtelten Methode geworfen werden. Das erlaubt, dass man Methoden, die man zum Beispiel bei mehreren API-Methoden benötigt, bequem auslagern kann.
  
 ==== Validierung des JWT ==== ==== Validierung des JWT ====
Zeile 22: Zeile 54:
 </WRAP> </WRAP>
  
-Es ist anzumerken, dass Exceptions in aller Regel in Bezug auf die Performanz schlechter abschneiden als die entsprechenden Checks. Daher sollte man Exceptions nie in "Schönwetter"-Fällen benutzen, sondern höchstens in unerwarteten Situationen. Ein invalides Token, bzw. allgemein ein ungültiger API-Aufruf, ist in unserem Fall unerwartet und kann mittels Exceptions gelöst werden. Werden aber viele ungültige API-Aufrufe erwartet, sollte man eine Exception-freie Alternative in Erwägung ziehen. +Wenn nun zudem Informationen wie das "Subject" aus dem JWT herausgelesen werden müssen, ergibt es keinen Sinn, eine separate "Exception"-basierte Validierung zu machen. Man kann die Validierung und das Auslesen direkt kombinieren. Nutzt man zudem die ResponseStatusException, hat man eine Methode, die man in mehreren API-Methoden einsetzen kann.
- +
-Wenn zudem Informationen wie das "Subject" aus dem JWT herausgelesen werden müssen, ergibt es keinen Sinn dies separat zu machen.+
  
 <code java> <code java>
 +public String verifyTokenAndExtractSubject() {
 +    try{
 +        String token = extractTokenFromHeader();
 +        return extractSubject(token);
 +    } catch (Exception e) {
 +        // Exception mitschicken
 +        // throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, "Invalid token", e);
  
 +        // Exception loggen
 +        log.warn("Invalid token", e);
 +        throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, "Invalid token");
 +    }
 +}
 +
 +private String extractSubject(String token) {
 +    return Jwts.parserBuilder()
 +            .setSigningKey(key)
 +            .build()
 +            .parseClaimsJws(token)
 +            .getBody()
 +            .getSubject();
 +}
 +
 +private String extractTokenFromHeader() {
 +    ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
 +    if (attributes == null){
 +        return null;
 +    }
 +    String authHeader = attributes.getRequest().getHeader("Authorization");
 +    if (authHeader == null || !authHeader.startsWith("Bearer ")) {
 +        return null;
 +    }
 +    return authHeader.substring(7);
 +}
 </code> </code>
  
  • de/modul/ffit/3-jahr/java/learningunits/lu10/a.1762726906.txt.gz
  • Zuletzt geändert: 2025/11/09 23:21
  • von apeter