Heim > Java > javaLernprogramm > Hauptteil

Anmeldesystem mit JWT-Token und E-Mail-Reset-Passwort

Barbara Streisand
Freigeben: 2024-11-24 22:48:13
Original
294 Leute haben es durchsucht

Login system with JWT token and email reset password

Einführung

Die Spring Login-Anwendung ist ein sicheres und robustes Benutzerverwaltungssystem, das mit Spring Boot erstellt wurde. Dieses Projekt demonstriert moderne Ansätze zur Implementierung von Authentifizierungs-, Autorisierungs- und Benutzerkontofunktionen. Zu den wichtigsten Funktionen gehören die Benutzerregistrierung, die sichere Passwortverwaltung mit BCrypt, das Zurücksetzen des Passworts per E-Mail und die JWT-Authentifizierung (JSON Web Token). Diese Anwendung wurde im Hinblick auf Erweiterbarkeit und Skalierbarkeit entwickelt und dient als hervorragende Grundlage für Projekte, die Benutzerverwaltung und rollenbasierte Zugriffskontrolle erfordern.

Durch die Nutzung der leistungsstarken Tools von Spring wie Spring Security, Spring Data JPA und JavaMailSender gewährleistet dieses Projekt Best Practices in Bezug auf Sicherheit, Wartbarkeit und Benutzerfreundlichkeit der Integration. Unabhängig davon, ob Sie eine kleine Webanwendung oder ein großes Unternehmenssystem erstellen, bietet dieses Projekt einen praktischen, gut strukturierten Ausgangspunkt für die sichere Verwaltung von Benutzerkonten.


Konfiguration

Pom.xml-Abhängigkeiten

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
        </dependency>


        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-mail</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Docker

Um die PostgreSQL-Datenbank auszuführen, erstellen Sie eine docker-compose.yaml-Datei:

services:
  postgres:
    image: postgres:latest
    ports:
      - "5432:5432"
    environment:
      - POSTGRES_DB=database
      - POSTGRES_USER=admin
      - POSTGRES_PASSWORD=admin
    volumes:
      - postgres_data:/var/lib/postgresql/data

volumes:
  postgres_data:

Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Ausführen:

docker compose up -d
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

application.properties

spring.application.name=login_app

spring.datasource.url=jdbc:postgresql://localhost:5432/database
spring.datasource.username=admin
spring.datasource.password=admin

spring.mail.host=sandbox.smtp.mailtrap.io
spring.mail.port=2525


spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true
spring.mail.default-encoding=UTF-8


spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true

spring.config.import=classpath:env.properties

jwt.public.key=classpath:public.key
jwt.private.key=classpath:private.key

Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

env.properties

spring.mail.username=<Get in your mailtrap account>
spring.mail.password=<Get in your mailtrap account>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Wie erstelle ich asymmetrische Schlüssel?

Sehen Sie in diesem Beitrag, wie man asymmetrische Schlüssel generiert


Projektstruktur

login_app/
├── .mvn/                       # Maven folder (Maven configurations)
├── src/
│   ├── main/
│   │   ├── java/
│   │   │   └── dev/
│   │   │       └── mspilari/
│   │   │           └── login_app/
│   │   │               ├── configs/           # Security, authentication, and other configurations
│   │   │               ├── domains/           # Main application domains
│   │   │               │   ├── email/         # Email-related logic
│   │   │               │   └── user/          # User-related logic
│   │   │               ├── exceptions/        # Custom exceptions and error handling
│   │   │               └── utils/             # Utilities and helpers
│   │   └── resources/                         # Resources (e.g., configuration files)
│   └── test/                                  # Application tests
├── target/                                    # Build folder generated by Maven
├── .gitattributes                             # Git attributes configuration
├── .gitignore                                 # Git ignore file
├── docker-compose.yaml                        # Docker Compose configuration
├── HELP.md                                    # Project help documentation
├── mvnw                                       # Maven Wrapper script for Linux
├── mvnw.cmd                                   # Maven Wrapper script for Windows
└── pom.xml                                    # Maven configuration file
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Merkmale

  • Benutzerregistrierung mit E-Mail- und Passwortvalidierung
  • Melden Sie sich mit JWT-Authentifizierung an
  • Passwortwiederherstellung mit E-Mail-Link-Zustellung
  • Passwort-Reset über Link mit temporärem Token
  • Feldvalidierung und Fehlerbehandlung

Code

Konfigurationsverzeichnis

BCryptPasswordConfig.java

package dev.mspilari.login_app.configs;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

@Configuration
public class BCryptPasswordConfig {

    @Bean
    public BCryptPasswordEncoder bPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Code-Aufschlüsselung

  1. @Konfiguration

    • Diese Annotation teilt Spring mit, dass die Klasse Bean-Definitionen enthält.
    • Mit @Configuration annotierte Klassen werden während des Anwendungsstarts verarbeitet, und die Rückgabewerte aller mit @Bean annotierten Methoden werden als verwaltete Beans zum Spring-Anwendungskontext hinzugefügt.
  2. @Bean

    • Die @Bean-Annotation der bPasswordEncoder()-Methode gibt an, dass diese Methode ein Objekt zurückgibt, das als Bean im Spring-Anwendungskontext registriert werden sollte.
    • Dadurch kann das BCryptPasswordEncoder-Objekt überall in der Anwendung eingefügt werden, wo es benötigt wird.
  3. BCryptPasswordEncoder

    • Dies ist eine von Spring Security bereitgestellte Dienstprogrammklasse zum Kodieren von Passwörtern.
    • Es verwendet den BCrypt-Hashing-Algorithmus, der als starke und sichere Methode zum Hashen von Passwörtern gilt. Der Algorithmus fügt dem Passwort vor dem Hashing automatisch ein „Salt“ hinzu und macht es so resistent gegen Wörterbuchangriffe und Rainbow-Table-Angriffe.
  4. Methode bPasswordEncoder()

    • Wenn diese Methode vom Spring-Framework aufgerufen wird, erstellt sie eine neue Instanz von BCryptPasswordEncoder und macht sie im Anwendungskontext verfügbar.
    • Andere Klassen in der Anwendung können diese Bean dann automatisch verknüpfen, um Passwörter zu verschlüsseln oder abzugleichen.

JwtConfig.java

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
        </dependency>


        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-mail</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Code-Aufschlüsselung

1. Anmerkungen auf Klassenebene

services:
  postgres:
    image: postgres:latest
    ports:
      - "5432:5432"
    environment:
      - POSTGRES_DB=database
      - POSTGRES_USER=admin
      - POSTGRES_PASSWORD=admin
    volumes:
      - postgres_data:/var/lib/postgresql/data

volumes:
  postgres_data:

Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
  • Gibt an, dass es sich um eine Spring-Konfigurationsklasse handelt, in der Beans (von Spring verwaltete Komponenten) definiert sind.
  • Die hier definierten Beans stehen im Spring Application Context für die Abhängigkeitsinjektion zur Verfügung.

2. RSA-Schlüssel aus der Konfiguration einfügen

docker compose up -d
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
  • @Value wird verwendet, um den öffentlichen Schlüssel und privaten Schlüssel aus der Eigenschaftendatei der Anwendung (z. B. application.yml oder application.properties) einzufügen.
  • Diese Schlüssel werden voraussichtlich in den Eigenschaften enthalten sein als:
spring.application.name=login_app

spring.datasource.url=jdbc:postgresql://localhost:5432/database
spring.datasource.username=admin
spring.datasource.password=admin

spring.mail.host=sandbox.smtp.mailtrap.io
spring.mail.port=2525


spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true
spring.mail.default-encoding=UTF-8


spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true

spring.config.import=classpath:env.properties

jwt.public.key=classpath:public.key
jwt.private.key=classpath:private.key

Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

3. JWT-Encoder-Bean

spring.mail.username=<Get in your mailtrap account>
spring.mail.password=<Get in your mailtrap account>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
  • Zweck: Erstellt eine Bean zum Codieren (Generieren) von JWT-Tokens.
  • Schritte:
    1. RSA-Schlüssel erstellen:
      • RSAKey.Builder erstellt eine JWK-Darstellung (JSON Web Key) des öffentlichen/privaten RSA-Schlüsselpaars.
    2. JWK-Set erstellen:
      • ImmutableJWKSet speichert den Schlüssel in einem Set. Dieses Set wird von Nimbus JOSE-Bibliotheken zum Signieren von Token verwendet.
    3. NimbusJwtEncoder:
      • Dieser Encoder verwendet das ImmutableJWKSet, um Token mit dem privaten Schlüssel zu kodieren und zu signieren.

4. JWT-Decoder-Bean

login_app/
├── .mvn/                       # Maven folder (Maven configurations)
├── src/
│   ├── main/
│   │   ├── java/
│   │   │   └── dev/
│   │   │       └── mspilari/
│   │   │           └── login_app/
│   │   │               ├── configs/           # Security, authentication, and other configurations
│   │   │               ├── domains/           # Main application domains
│   │   │               │   ├── email/         # Email-related logic
│   │   │               │   └── user/          # User-related logic
│   │   │               ├── exceptions/        # Custom exceptions and error handling
│   │   │               └── utils/             # Utilities and helpers
│   │   └── resources/                         # Resources (e.g., configuration files)
│   └── test/                                  # Application tests
├── target/                                    # Build folder generated by Maven
├── .gitattributes                             # Git attributes configuration
├── .gitignore                                 # Git ignore file
├── docker-compose.yaml                        # Docker Compose configuration
├── HELP.md                                    # Project help documentation
├── mvnw                                       # Maven Wrapper script for Linux
├── mvnw.cmd                                   # Maven Wrapper script for Windows
└── pom.xml                                    # Maven configuration file
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
  • Zweck: Erstellt eine Bean zum Dekodieren und Überprüfen von JWT-Tokens.
  • Schritte:
    1. Verifizierung des öffentlichen Schlüssels:
      • NimbusJwtDecoder.withPublicKey() wird mit dem öffentlichen RSA-Schlüssel konfiguriert. Es überprüft die Signatur von Token.
    2. Decoder erstellen:
      • Die Methode build() erstellt die Decoder-Instanz.

Wie die JWT-Kodierung und -Dekodierung funktioniert

  1. JWT-Kodierung (Token-Generierung):

    • Die JwtEncoder-Bean wird zum Erstellen eines signierten JWT-Tokens verwendet. Dieses Token enthält normalerweise Benutzerinformationen (z. B. Benutzername, Rollen usw.) als Ansprüche und ist mit dem privaten RSA-Schlüssel signiert.
    • Beispiel:
    package dev.mspilari.login_app.configs;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
    
    @Configuration
    public class BCryptPasswordConfig {
    
        @Bean
        public BCryptPasswordEncoder bPasswordEncoder() {
            return new BCryptPasswordEncoder();
        }
    }
    
    
    Nach dem Login kopieren
    Nach dem Login kopieren
    Nach dem Login kopieren
  2. JWT-Dekodierung (Token-Verifizierung):

    • Die JwtDecoder-Bean wird zum Dekodieren und Überprüfen des Tokens mithilfe des öffentlichen RSA-Schlüssels verwendet. Dadurch wird sichergestellt, dass das Token:
      • Wurde vom Server ausgestellt (Signaturüberprüfung).
      • Wurde nicht manipuliert.
    • Beispiel:
    package dev.mspilari.login_app.configs;
    
    import java.security.interfaces.RSAPrivateKey;
    import java.security.interfaces.RSAPublicKey;
    
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.oauth2.jwt.JwtDecoder;
    import org.springframework.security.oauth2.jwt.JwtEncoder;
    import org.springframework.security.oauth2.jwt.NimbusJwtDecoder;
    import org.springframework.security.oauth2.jwt.NimbusJwtEncoder;
    
    import com.nimbusds.jose.jwk.JWKSet;
    import com.nimbusds.jose.jwk.RSAKey;
    import com.nimbusds.jose.jwk.source.ImmutableJWKSet;
    
    @Configuration
    public class JwtConfig {
        @Value("${jwt.public.key}")
        private RSAPublicKey publicKey;
    
        @Value("${jwt.private.key}")
        private RSAPrivateKey privateKey;
    
        @Bean
        public JwtEncoder jwtEncoder() {
            var jwk = new RSAKey.Builder(this.publicKey).privateKey(this.privateKey).build();
    
            var jwks = new ImmutableJWKSet<>(new JWKSet(jwk));
    
            return new NimbusJwtEncoder(jwks);
        }
    
        @Bean
        public JwtDecoder jwtDecoder() {
            return NimbusJwtDecoder.withPublicKey(this.publicKey).build();
        }
    }
    
    Nach dem Login kopieren
    Nach dem Login kopieren

SecurityConfig.java

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
        </dependency>


        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-mail</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

1. Anmerkungen auf Klassenebene

services:
  postgres:
    image: postgres:latest
    ports:
      - "5432:5432"
    environment:
      - POSTGRES_DB=database
      - POSTGRES_USER=admin
      - POSTGRES_PASSWORD=admin
    volumes:
      - postgres_data:/var/lib/postgresql/data

volumes:
  postgres_data:

Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
  • @Configuration: Markiert diese Klasse als Spring-Konfiguration, die Beans definiert.
  • @EnableWebSecurity: Aktiviert die Web-Sicherheitsfunktionen von Spring Security.
  • @EnableMethodSecurity: Aktiviert Sicherheitsanmerkungen auf Methodenebene wie @PreAuthorize oder @Secured. Dadurch können Sie den Zugriff auf bestimmte Methoden in Ihrer Anwendung basierend auf Rollen, Berechtigungen oder Bedingungen steuern.

2. SecurityFilterChain Bean

docker compose up -d
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
  • Definiert die Sicherheitsfilterkette für die Anwendung. Eine Filterkette ist eine Folge von Sicherheitsfiltern, die auf eingehende HTTP-Anfragen angewendet werden.

3. CSRF-Schutz

spring.application.name=login_app

spring.datasource.url=jdbc:postgresql://localhost:5432/database
spring.datasource.username=admin
spring.datasource.password=admin

spring.mail.host=sandbox.smtp.mailtrap.io
spring.mail.port=2525


spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true
spring.mail.default-encoding=UTF-8


spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true

spring.config.import=classpath:env.properties

jwt.public.key=classpath:public.key
jwt.private.key=classpath:private.key

Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
  • Der CSRF (Cross-Site Request Forgery)-Schutz ist deaktiviert.
    • CSRF-Schutz ist für zustandslose APIs oft nicht erforderlich, da Token (wie JWT) bereits eine Möglichkeit bieten, nicht autorisierte Anfragen zu verhindern.
    • Die Deaktivierung vereinfacht die Sicherheitskonfiguration für diese JWT-basierte API.

4. Autorisierungsregeln

spring.mail.username=<Get in your mailtrap account>
spring.mail.password=<Get in your mailtrap account>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
  • Konfiguriert, welche Endpunkte eine Authentifizierung erfordern:
    • Alle zulassen:
    • POST-Anfragen an Endpunkte wie /user/register, /user/login, /user/redeem-password und /user/reset-password stehen allen offen (keine Authentifizierung erforderlich).
    • Diese Endpunkte werden wahrscheinlich für die Benutzerregistrierung, Anmeldung und Passwortwiederherstellung/-zurücksetzung verwendet, auf die normalerweise ohne Anmeldung zugegriffen werden kann.
    • Andere Anfragen authentifizieren:
    • Alle anderen Endpunkte (anyRequest) erfordern eine Authentifizierung.

5. JWT-Validierung

login_app/
├── .mvn/                       # Maven folder (Maven configurations)
├── src/
│   ├── main/
│   │   ├── java/
│   │   │   └── dev/
│   │   │       └── mspilari/
│   │   │           └── login_app/
│   │   │               ├── configs/           # Security, authentication, and other configurations
│   │   │               ├── domains/           # Main application domains
│   │   │               │   ├── email/         # Email-related logic
│   │   │               │   └── user/          # User-related logic
│   │   │               ├── exceptions/        # Custom exceptions and error handling
│   │   │               └── utils/             # Utilities and helpers
│   │   └── resources/                         # Resources (e.g., configuration files)
│   └── test/                                  # Application tests
├── target/                                    # Build folder generated by Maven
├── .gitattributes                             # Git attributes configuration
├── .gitignore                                 # Git ignore file
├── docker-compose.yaml                        # Docker Compose configuration
├── HELP.md                                    # Project help documentation
├── mvnw                                       # Maven Wrapper script for Linux
├── mvnw.cmd                                   # Maven Wrapper script for Windows
└── pom.xml                                    # Maven configuration file
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
  • Konfiguriert die Anwendung als OAuth 2.0-Ressourcenserver, der Anfragen mithilfe von JWT-Tokens validiert.
  • JWT-Decoder:
    • Die JwtDecoder-Bean (bereitgestellt von JwtConfig) wird verwendet, um eingehende JWT-Tokens für Anforderungen an sichere Endpunkte zu überprüfen.

Wie das funktioniert

  1. CSRF deaktiviert: Da es sich um eine API handelt, die auf zustandsloser JWT-Authentifizierung basiert, ist die Deaktivierung von CSRF gängige Praxis.
  2. Autorisierungsregeln:
    • Nicht authentifizierte Benutzer können nur auf die explizit zugelassenen Endpunkte zugreifen (z. B. /user/register oder /user/login).
    • Für jede andere Anfrage ist ein gültiges JWT-Token erforderlich.
  3. JWT-Validierung:
    • Spring Security extrahiert automatisch den Authorization-Header aus eingehenden Anfragen.
    • Wenn der Header ein gültiges JWT-Token enthält, wird die Anfrage authentifiziert und der Benutzerkontext hergestellt.
    • Wenn das Token ungültig ist oder fehlt, wird die Anfrage abgelehnt.

Domains-Verzeichnis

E-Mail-Verzeichnis

Dienstleistungsverzeichnis
<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
        </dependency>


        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-mail</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Benutzerverzeichnis

Controller-Verzeichnis
services:
  postgres:
    image: postgres:latest
    ports:
      - "5432:5432"
    environment:
      - POSTGRES_DB=database
      - POSTGRES_USER=admin
      - POSTGRES_PASSWORD=admin
    volumes:
      - postgres_data:/var/lib/postgresql/data

volumes:
  postgres_data:

Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

DTO-Verzeichnis

UserDto.java

docker compose up -d
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

UserRedeemPasswordDto.java

spring.application.name=login_app

spring.datasource.url=jdbc:postgresql://localhost:5432/database
spring.datasource.username=admin
spring.datasource.password=admin

spring.mail.host=sandbox.smtp.mailtrap.io
spring.mail.port=2525


spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true
spring.mail.default-encoding=UTF-8


spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true

spring.config.import=classpath:env.properties

jwt.public.key=classpath:public.key
jwt.private.key=classpath:private.key

Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

UserResetPasswordDto.java

spring.mail.username=<Get in your mailtrap account>
spring.mail.password=<Get in your mailtrap account>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Entitätsverzeichnis

UserEntity.java

login_app/
├── .mvn/                       # Maven folder (Maven configurations)
├── src/
│   ├── main/
│   │   ├── java/
│   │   │   └── dev/
│   │   │       └── mspilari/
│   │   │           └── login_app/
│   │   │               ├── configs/           # Security, authentication, and other configurations
│   │   │               ├── domains/           # Main application domains
│   │   │               │   ├── email/         # Email-related logic
│   │   │               │   └── user/          # User-related logic
│   │   │               ├── exceptions/        # Custom exceptions and error handling
│   │   │               └── utils/             # Utilities and helpers
│   │   └── resources/                         # Resources (e.g., configuration files)
│   └── test/                                  # Application tests
├── target/                                    # Build folder generated by Maven
├── .gitattributes                             # Git attributes configuration
├── .gitignore                                 # Git ignore file
├── docker-compose.yaml                        # Docker Compose configuration
├── HELP.md                                    # Project help documentation
├── mvnw                                       # Maven Wrapper script for Linux
├── mvnw.cmd                                   # Maven Wrapper script for Windows
└── pom.xml                                    # Maven configuration file
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Enums-Verzeichnis

Role.java

package dev.mspilari.login_app.configs;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

@Configuration
public class BCryptPasswordConfig {

    @Bean
    public BCryptPasswordEncoder bPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Repository-Verzeichnis

UserRepository.java

package dev.mspilari.login_app.configs;

import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.oauth2.jwt.JwtDecoder;
import org.springframework.security.oauth2.jwt.JwtEncoder;
import org.springframework.security.oauth2.jwt.NimbusJwtDecoder;
import org.springframework.security.oauth2.jwt.NimbusJwtEncoder;

import com.nimbusds.jose.jwk.JWKSet;
import com.nimbusds.jose.jwk.RSAKey;
import com.nimbusds.jose.jwk.source.ImmutableJWKSet;

@Configuration
public class JwtConfig {
    @Value("${jwt.public.key}")
    private RSAPublicKey publicKey;

    @Value("${jwt.private.key}")
    private RSAPrivateKey privateKey;

    @Bean
    public JwtEncoder jwtEncoder() {
        var jwk = new RSAKey.Builder(this.publicKey).privateKey(this.privateKey).build();

        var jwks = new ImmutableJWKSet<>(new JWKSet(jwk));

        return new NimbusJwtEncoder(jwks);
    }

    @Bean
    public JwtDecoder jwtDecoder() {
        return NimbusJwtDecoder.withPublicKey(this.publicKey).build();
    }
}
Nach dem Login kopieren
Nach dem Login kopieren

Dienstleistungsverzeichnis

UserService.java

@Configuration
Nach dem Login kopieren

Ausnahmeverzeichnis

GlobalException.java

@Value("${jwt.public.key}")
private RSAPublicKey publicKey;

@Value("${jwt.private.key}")
private RSAPrivateKey privateKey;
Nach dem Login kopieren

Utils-Verzeichnis

JwtActions.java

  jwt.public.key=<your-public-key>
  jwt.private.key=<your-private-key>
Nach dem Login kopieren

Abschluss

In diesem Projekt haben wir mit Spring Boot erfolgreich ein sicheres und funktionsreiches Benutzerauthentifizierungssystem implementiert. Über die Kernfunktionen wie Benutzerregistrierung, Anmeldung und JWT-basierte Authentifizierung hinaus verfügt die Anwendung auch über ein Passwortwiederherstellungssystem. Benutzer können ihre Passwörter über einen E-Mail-Link zurücksetzen, um einen reibungslosen und sicheren Wiederherstellungsprozess zu gewährleisten.

Um die E-Mail-basierte Passwortwiederherstellung zu erleichtern, haben wir Spring Email mit Mailtrap integriert, einem sicheren und effizienten E-Mail-Testdienst. Dadurch kann die Anwendung Links zum Zurücksetzen des Passworts mit temporären Token senden und gleichzeitig sicherstellen, dass E-Mails sicher gesendet und in einer kontrollierten Umgebung getestet werden. Dieses Setup zeigt, wie man sensible Arbeitsabläufe wie die Passwortwiederherstellung handhabt, ohne dass echte Benutzer während der Entwicklung und beim Testen potenziellen Problemen ausgesetzt werden.

Die Kombination aus sicheren Authentifizierungsverfahren, robustem Passwortmanagement und nahtloser E-Mail-Integration macht diese Anwendung zu einer zuverlässigen Grundlage für jedes moderne Websystem. Entwickler können diese Praktiken an ihre spezifischen Anforderungen anpassen und so sowohl Skalierbarkeit als auch Benutzervertrauen gewährleisten. Durch den Einsatz von Best Practices und Tools wie Spring Security und Mailtrap haben wir gezeigt, wie man mit Leichtigkeit sichere, benutzerorientierte Anwendungen erstellt.


? Referenz

  • Frühlingssicherheit
  • MailTrap
  • Frühlings-E-Mail

? Projekt-Repository

  • Projekt-Repository auf Github

? Sprechen Sie mit mir

  • LinkedIn
  • Github
  • Portfolio

Das obige ist der detaillierte Inhalt vonAnmeldesystem mit JWT-Token und E-Mail-Reset-Passwort. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:dev.to
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Neueste Artikel des Autors
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage