Heim  >  Artikel  >  Java  >  Microservices mit Spring Security sichern: JWT implementieren

Microservices mit Spring Security sichern: JWT implementieren

PHPz
PHPzOriginal
2024-08-24 06:42:38398Durchsuche

JSON-WEB-TOKEN (JWT)

JWT (JSON Web Token) ist eine Methode zur sicheren Übertragung von Informationen zwischen zwei Parteien (z. B. einem Client und einem Server) als JSON-Objekt. Es ist so konzipiert, dass es kompakt und URL-sicher ist, sodass es problemlos in URLs und Headern weitergegeben werden kann.

  1. Kopfzeile
  2. Nutzlast
  3. Unterschrift

Kopfzeile
Der Header besteht typischerweise aus zwei Teilen: dem Typ des Tokens (JWT) und dem verwendeten Signaturalgorithmus, wie z. B. HMAC SHA256 oder RSA.

{
„alg“: „HS256“,
„typ“: „JWT“
}

Nutzlast
Hier werden die eigentlichen Daten gespeichert. Es kann Informationen wie die Benutzer-ID, Rollen, Ablaufzeit und andere Ansprüche (Daten über den Benutzer oder die Sitzung) enthalten.

{
„email“: „ayushstwt@gmail.com“,
„name“: „Ayush“
}

Unterschrift
Stellt die Integrität des Tokens sicher. Dies ist eine Sicherheitsfunktion, die sicherstellt, dass das Token nicht verändert wurde. Es wird durch die Kombination des codierten Headers und der Nutzlast mit einem geheimen Schlüssel unter Verwendung des angegebenen Algorithmus erstellt. Mithilfe der Signatur kann der Server überprüfen, ob das Token legitim ist und nicht manipuliert wurde.

Die Vorteile von JWT

Keine Notwendigkeit, Anmeldeinformationen wiederholt zu senden: Mit JWT müssen Sie nicht bei jeder Anfrage Ihren Benutzernamen und Ihr Passwort senden. Stattdessen melden Sie sich einmal an und der Server gibt Ihnen ein Token. Anschließend senden Sie diesen Token bei jeder Anfrage zum Nachweis Ihrer Identität mit, wodurch der Prozess sicherer und effizienter wird.

Eingebauter Ablauf: Jedes JWT verfügt über eine Ablaufzeit, was bedeutet, dass es nur für einen bestimmten Zeitraum gültig ist. Dies verringert das Risiko eines langfristigen Missbrauchs, wenn ein Token auf irgendeine Weise abgefangen wird. Nach Ablauf muss sich der Benutzer erneut anmelden, um ein neues Token zu erhalten, wodurch eine zusätzliche Sicherheitsebene hinzugefügt wird.

JWT mit Spring Boot verwaltet die Benutzerauthentifizierung sicher, indem nach der Anmeldung Token ausgegeben werden. Diese Token werden bei jeder Anfrage gesendet und gewährleisten so eine sichere, zustandslose Kommunikation ohne wiederholtes Senden von Anmeldeinformationen.

Zustandslose Kommunikation bedeutet, dass sich der Server vergangene Anfragen nicht merkt. Jede Anfrage enthält alles, was benötigt wird (wie ein JWT), sodass der Server keine Sitzungsinformationen speichert.

Die Implementierung von JWT in einer Java Spring Boot-Anwendung umfasst mehrere Schritte. Hier ist eine vereinfachte Gliederung, um Ihnen den Einstieg zu erleichtern:

1. Abhängigkeiten hinzufügen

Fügen Sie die erforderlichen Abhängigkeiten in Ihre pom.xml-Datei ein

                <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-api</artifactId>
            <version>0.12.5</version>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-impl</artifactId>
            <version>0.12.5</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-jackson</artifactId>
            <version>0.12.5</version>
            <scope>runtime</scope>
        </dependency>

Alle Abhängigkeiten, die wir zum Erstellen der Spring-Boot-Anwendung mit JWT benötigen

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.3.3</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.tier3Hub</groupId>
    <artifactId>user-auth-service</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>user-auth-service</name>
    <description>The user-auth-service is a microservice responsible for handling user authentication and authorization within a distributed system. It is designed to manage user login, registration, and secure access to various services using robust security practices. This service implements authentication mechanisms like JSON Web Tokens (JWT) and integrates with OAuth 2.0 for third-party authentication. Built with Spring Boot, it ensures scalability, reliability, and easy integration with other microservices in the system.</description>
    <url/>
    <licenses>
        <license/>
    </licenses>
    <developers>
        <developer/>
    </developers>
    <scm>
        <connection/>
        <developerConnection/>
        <tag/>
        <url/>
    </scm>
    <properties>
        <java.version>21</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</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>io.jsonwebtoken</groupId>
            <artifactId>jjwt-api</artifactId>
            <version>0.12.5</version>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-impl</artifactId>
            <version>0.12.5</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-jackson</artifactId>
            <version>0.12.5</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </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>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springdoc</groupId>
            <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
            <version>2.5.0</version>
        </dependency>
        <dependency>
            <groupId>org.modelmapper</groupId>
            <artifactId>modelmapper</artifactId>
            <version>3.1.1</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

Wir verwenden verschiedene Arten von Abhängigkeiten wie

  • Spring Boot Starter Actuator: 3.3.3 – Fügt produktionsbereite Funktionen wie Überwachung und Zustandsprüfungen hinzu.
  • Spring Boot Starter Data JPA: 3.3.3 – Vereinfacht Datenbankinteraktionen mit JPA-Unterstützung.
  • Spring Boot Starter Security: 3.3.3 – Bietet Sicherheitsfunktionen wie Authentifizierung und Autorisierung.
  • Spring Boot Starter Web: 3.3.3 – Unterstützt die Erstellung von Webanwendungen, einschließlich RESTful-Diensten.
  • JJWT API: 0.12.5 – Verwaltet die JWT-Erstellung und -Analyse für eine sichere Token-Verwaltung.
  • JJWT Impl: 0.12.5 – Implementiert Kernfunktionen von JWT.
  • JJWT Jackson: 0.12.5 – Ermöglicht die JWT-JSON-Analyse mit Jackson.
  • MySQL Connector: Runtime – Verbindet Ihre Anwendung mit einer MySQL-Datenbank.
  • Lombok: Nicht angegeben – Reduziert Boilerplate-Code mit Anmerkungen.
  • Spring Boot Starter Test: 3.3.3 – Bietet Testunterstützung für Spring Boot-Anwendungen.
  • Spring Security Test: 3.3.3 – Hilft beim Testen von Sicherheitskonfigurationen.
  • Spring Boot Starter-Validierung: 3.3.3 – Fügt Validierungsunterstützung für Anforderungs- und Antwortobjekte hinzu.
  • SpringDoc OpenAPI Starter WebMVC-Benutzeroberfläche: 2.5.0 – Integriert die Swagger-Benutzeroberfläche für die API-Dokumentation.
  • ModelMapper: 3.1.1 – Vereinfacht die Objektzuordnung zwischen verschiedenen Ebenen.

*2. Projektstruktur *

Securing Microservices with Spring Security: Implementing JWT

3. Fügen Sie die Konfiguration in der Datei application.properties hinzu

spring.application.name=user-auth-service

server.port=8000

spring.datasource.url=jdbc:mysql://localhost:3306/auth_services
spring.datasource.username=root
spring.datasource.password=ayush@123

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

#debug logs
logging.level.org.springframework.security=debug

spring.main.allow-circular-references=true 

4. Erstellen Sie die USER-Entität

package com.tier3Hub.user_auth_service.entity;

import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;
import java.util.List;

@AllArgsConstructor
@NoArgsConstructor
@Data
@Builder
@Table
@Entity(name = "User")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String username;
    private String password;
    private String email;
    private String phoneNumber;
    private List<String> roles;
    private LocalDateTime createdAt;
    private LocalDateTime updatedAt;
}

** 5. Erstellen Sie die Service- und Repository-Klasse und -Schnittstelle**

Repository.java

package com.tier3Hub.user_auth_service.Repository;

import com.tier3Hub.user_auth_service.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;

public interface AuthRepository extends JpaRepository<User, Long> {

    User findByUsername(String username);
}

service.java

package com.tier3Hub.user_auth_service.service;

import com.tier3Hub.user_auth_service.dto.LoginResponse;
import com.tier3Hub.user_auth_service.dto.RegisterDTO;
import com.tier3Hub.user_auth_service.dto.RegisterResponse;

public interface AuthService {
    RegisterResponse register(RegisterDTO registerDTO);
}

6. Erstellen Sie die DTOs für die Anmeldung und Anmeldeanfrage und -antwort

LoginDTO.java erstellen

package com.tier3Hub.user_auth_service.dto;

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@AllArgsConstructor
@NoArgsConstructor
@Data
public class LoginDTO {
    @NotBlank(message = "Username is required")
    @Size(min = 3, max = 20, message = "Username must be between 3 and 20 characters")
    private String username;

    @NotBlank(message = "Password is required")
    private String password;
}

loginResponse.java

package com.tier3Hub.user_auth_service.dto;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class LoginResponse {
    private String accessToken;
    private String tokenType = "Bearer";
}

RegisterDTO.java

package com.tier3Hub.user_auth_service.dto;

import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@AllArgsConstructor
@NoArgsConstructor
@Data
public class RegisterDTO {
    @NotBlank(message = "Username is required")
    @Size(min = 3, max = 20, message = "Username must be between 3 and 20 characters")
    private String username;

    @NotBlank(message = "Password is required")
    @Size(min = 8, message = "Password must be at least 8 characters")
    private String password;

    @NotBlank(message = "Email is required")
    @Email(message = "Email should be valid")
    private String email;
}

RegisterResponse.java

package com.tier3Hub.user_auth_service.dto;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;

@AllArgsConstructor
@NoArgsConstructor
@Data
public class RegisterResponse {
    private Long id;
    private String username;
    private String email;
    private LocalDateTime createdAt;
    private LocalDateTime updatedAt;
}

*7. Zum Senden benutzerdefinierter Antworten von der API verwenden wir ResponseHandler.java *

package com.tier3Hub.user_auth_service.utils;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;

import java.util.HashMap;
import java.util.Map;

public class ResponseHandler {
    public static ResponseEntity<Object> generateResponse(String message, HttpStatus status, Object responseObj) {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("message", message);
        map.put("status", status.value());
        map.put("data", responseObj);
        return new ResponseEntity<Object>(map, status);
    }

}

8. for storing some constants we create the class inside the utils package that is ApplicationConstants.java

package com.tier3Hub.user_auth_service.utils;

public class AppConstants {
    public static final String[] PUBLIC_URLS = { "/v3/api-docs/**", "/swagger-ui/**", "/api/auth/register/**", "/api/auth/login/**","/api/auth/registerAdmin/**" };
}

9. for converting the object one to another we use the dependency that is model mapper for configuration that we create the class inside the config package that is ApplicationConfigs.java

package com.tier3Hub.user_auth_service.config;

import org.modelmapper.ModelMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ApplicationConfigs {
    @Bean
    public ModelMapper modelMapper()
    {
        return new ModelMapper();
    }
}

**
This is the basic setup that we do for every spring-boot application we create now securing the rest endpoint with JWT we started.
**

now inside the security package we create the class called JWTFilter.java

The JWTFilter is a custom Spring Security filter that intercepts HTTP requests to validate JWTs. It checks for the "Authorization" header, extracts the token, and retrieves the username. If the token is valid, it creates an authentication token with user details and sets it in the security context, allowing the application to recognize the authenticated user for further processing.

package com.tier3Hub.user_auth_service.security;

import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Service;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;

@Service
public class JWTFilter extends OncePerRequestFilter {
    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private JWTUtil jwtUtil;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
        String authorizationHeader = request.getHeader("Authorization");
        String username = null;
        String jwt = null;
        if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
            jwt = authorizationHeader.substring(7);
            username = jwtUtil.extractUsername(jwt);
        }
        if (username != null) {
            UserDetails userDetails = userDetailsService.loadUserByUsername(username);
            if (jwtUtil.validateToken(jwt)) {
                UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
                auth.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                SecurityContextHolder.getContext().setAuthentication(auth);
            }
        }
        chain.doFilter(request, response);
    }
}

create the class JWTUtil.java

The JWTUtil class manages JWT operations, including extracting usernames and expiration dates from tokens. It generates new tokens using a secret key and validates existing tokens by checking their expiration. The class uses HMAC for signing and includes methods to parse claims and determine if tokens are expired, ensuring secure authentication and authorization in the application.

package com.tier3Hub.user_auth_service.security;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import org.springframework.stereotype.Service;

import javax.crypto.SecretKey;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Service
public class JWTUtil {

    private String SECRET_KEY = "TaK+HaV^uvCHEFsEVfypW#7g9^k*Z8$V";

    private SecretKey getSigningKey() {
        return Keys.hmacShaKeyFor(SECRET_KEY.getBytes());
    }

    public String extractUsername(String token) {
        Claims claims = extractAllClaims(token);
        return claims.getSubject();
    }

    public Date extractExpiration(String token) {
        return extractAllClaims(token).getExpiration();
    }

    private Claims extractAllClaims(String token) {
        return Jwts.parser()
                .verifyWith(getSigningKey())
                .build()
                .parseSignedClaims(token)
                .getPayload();
    }

    private Boolean isTokenExpired(String token) {
        return extractExpiration(token).before(new Date());
    }

    public String generateToken(String username) {
        Map<String, Object> claims = new HashMap<>();
        return createToken(claims, username);
    }

    private String createToken(Map<String, Object> claims, String subject) {
        return Jwts.builder()
                .claims(claims)
                .subject(subject)
                .header().empty().add("typ","JWT")
                .and()
                .issuedAt(new Date(System.currentTimeMillis()))
                .expiration(new Date(System.currentTimeMillis() + 1000 * 60 * 50)) // 5 minutes expiration time
                .signWith(getSigningKey())
                .compact();
    }

    public Boolean validateToken(String token) {
        return !isTokenExpired(token);
    }
}

*configure the Spring security and add some modifictaion we create the class SecurityConfig.java *

The SecurityConfig class sets up security for the application using Spring Security. It defines access rules, allowing public endpoints while restricting others based on user roles. The class incorporates a JWT filter to validate tokens and uses BCrypt for password encoding. It also configures an authentication manager with a custom user details service for secure user authentication.

package com.tier3Hub.user_auth_service.config;

import com.tier3Hub.user_auth_service.security.JWTFilter;
import com.tier3Hub.user_auth_service.service.UserInfoConfigManager;
import com.tier3Hub.user_auth_service.utils.AppConstants;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
@EnableWebSecurity
public class SecurityConfig {
    @Autowired
    private JWTFilter jwtFilter;

    @Autowired
    private UserInfoConfigManager userInfoConfigManager;

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        return http.authorizeHttpRequests(request -> request
                        .requestMatchers(AppConstants.PUBLIC_URLS).permitAll()
                        .requestMatchers("/api/test/public/hello/**").hasAnyRole("USER","ADMIN")
                        .requestMatchers("/api/test/private/**").hasRole("ADMIN")
                        .anyRequest()
                        .authenticated())
                .csrf(AbstractHttpConfigurer::disable)
                .addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class)
                .build();
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userInfoConfigManager).passwordEncoder(passwordEncoder());
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration auth) throws Exception {
        return auth.getAuthenticationManager();
    }
}

The securityFilterChain method configures access rules for different API endpoints in the Spring application. It permits public URLs and applies role-based access control for user and admin roles. Role-based authentication restricts resource access based on user roles (e.g., USER, ADMIN). In Spring Boot, you define roles and configure security settings in the SecurityConfig class to specify access permissions. During user registration, assign roles, and use annotations like @PreAuthorize to enforce role checks in controllers. This approach enhances security, allows easy permission management, and simplifies user access rights as the application scales. Implementing role-based auth provides flexibility and maintainability for your user management system. CSRF protection is disabled, and a custom JWT filter is added to authenticate requests based on JSON Web Tokens, ensuring secure and controlled access to resources.

configureGlobal method handle configures global authentication settings in a Spring application. It uses a custom user details service for loading user data and a BCrypt password encoder for secure password hashing. Additionally, it provides an AuthenticationManager bean for handling authentication processes, ensuring a secure and efficient user authentication system that leverages strong password management practices.

create the endpoints for register and login

package com.tier3Hub.user_auth_service.Controller;


import com.tier3Hub.user_auth_service.dto.LoginDTO;
import com.tier3Hub.user_auth_service.dto.LoginResponse;
import com.tier3Hub.user_auth_service.dto.RegisterDTO;
import com.tier3Hub.user_auth_service.security.JWTUtil;
import com.tier3Hub.user_auth_service.service.AuthService;
import com.tier3Hub.user_auth_service.service.UserInfoConfigManager;
import com.tier3Hub.user_auth_service.utils.ResponseHandler;
import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api/auth")
public class AuthController {
    @Autowired
    JWTUtil jwtUtil;

    @Autowired
    AuthService authService;

    @Autowired
    AuthenticationManager authenticationManager;

    @Autowired
    private UserInfoConfigManager userInfoConfigManager;

    @PostMapping("/register")
    public ResponseEntity<Object> register(@Valid @RequestBody RegisterDTO registerDTO) {
        return ResponseHandler.generateResponse("User registered successfully", HttpStatus.OK, authService.register(registerDTO));
    }

    @PostMapping("/login")
    public ResponseEntity<Object> login(@Valid @RequestBody LoginDTO loginDTO) {
        try {
            Authentication authenticate = authenticationManager
                    .authenticate(new UsernamePasswordAuthenticationToken(loginDTO.getUsername(), loginDTO.getPassword()));
            UserDetails userDetails = userInfoConfigManager.loadUserByUsername(loginDTO.getUsername());
            String jwt = jwtUtil.generateToken(userDetails.getUsername());
            LoginResponse loginResponse = LoginResponse
                    .builder()
                    .accessToken(jwt)
                    .build();
            return ResponseHandler.generateResponse("User logged in successfully", HttpStatus.OK, loginResponse);
        }
        catch (Exception e)
        {
            return new ResponseEntity<>("Incorrect username or password", HttpStatus.BAD_REQUEST);
        }
    }
}

This login method in the AuthController handles user login requests. It takes a LoginDTO containing the username and password, validates them, and attempts authentication using the AuthenticationManager. Upon successful authentication, it retrieves user details and generates a JWT token using the JWTUtil class. The token is then included in a LoginResponse object and returned with a success message. If authentication fails, it catches the exception and returns a "Incorrect username or password" response with a 400 status code.

generateToken(String username): This method creates an empty claims map and calls the createToken method with the username as the subject. It serves as the entry point for token generation.

c*reateToken(Map claims, String subject):* This method builds the JWT using the Jwts.builder(). It sets the claims, subject, and token metadata, such as issue date and expiration time (set to 5 minutes). The token is then signed with a secret key and compacted into a string format for transmission.

Testing

now we run the application

Securing Microservices with Spring Security: Implementing JWT

and hit the URL here our application is runing on 8000 port

http://localhost:8000/swagger-ui/index.html

Die Verwendung von Swagger in Ihrem Projekt verbessert die API-Dokumentation und -Tests. Es bietet Entwicklern eine benutzerfreundliche Oberfläche, mit der sie Ihre APIs erkunden, Anforderungs-/Antwortstrukturen verstehen und Endpunkte direkt aus der Dokumentation testen können. Durch die Integration von Swagger ermöglichen Sie die automatische Generierung von API-Dokumenten basierend auf Ihren Codeanmerkungen und erleichtern so sowohl Front-End- als auch Back-End-Entwicklern eine effiziente Zusammenarbeit.

Securing Microservices with Spring Security: Implementing JWT

Zuerst registrieren wir den Benutzer

Securing Microservices with Spring Security: Implementing JWT

Wir bekommen die Antwort so

Securing Microservices with Spring Security: Implementing JWT

Danach melden wir den Benutzer an

Securing Microservices with Spring Security: Implementing JWT

Wir bekommen die Antwort so

Securing Microservices with Spring Security: Implementing JWT

Abschluss

Das Projekt implementiert die rollenbasierte Authentifizierung mithilfe von JWT (JSON Web Tokens) in einer Spring Boot-Anwendung. Es verfügt über einen sicheren Authentifizierungsmechanismus, mit dem sich Benutzer registrieren und anmelden können und ein JWT erhalten, das den Zugriff basierend auf den ihnen zugewiesenen Rollen (wie USER oder ADMIN) gewährt. Die SecurityConfig-Klasse konfiguriert Zugriffsberechtigungen und stellt sicher, dass öffentliche Endpunkte für alle zugänglich sind, während vertrauliche Vorgänge nur auf autorisierte Benutzer beschränkt werden. Die JWTUtil-Klasse übernimmt die Tokenerstellung, Validierung und Benutzerextraktion. Insgesamt erhöht dieses Setup die Sicherheit und ermöglicht eine nahtlose und robuste Zugriffskontrolle für die gesamte Anwendung.

Das Projekt verwendet ein umfassendes Sicherheits-Framework, das Spring Security für die Benutzerauthentifizierung und -autorisierung nutzt. Der AuthController erleichtert die Benutzerregistrierung und -anmeldung und generiert bei erfolgreicher Authentifizierung ein JWT. Die Anwendung verwendet einen JWTFilter, um Anfragen abzufangen und Token zu validieren, um sicherzustellen, dass nur authentifizierte Benutzer auf geschützte Ressourcen zugreifen können. Durch die Integration einer rollenbasierten Zugriffskontrolle stellt das Projekt ein flexibles und sicheres Benutzerverwaltungssystem bereit. Dieses Design verbessert nicht nur die Sicherheit, sondern verbessert auch das Benutzererlebnis, indem es die Notwendigkeit wiederholter Anmeldungen minimiert. Insgesamt bildet es eine solide Grundlage für den Aufbau skalierbarer und sicherer Microservices.

Sie können den vollständigen Quellcode für den Benutzerauthentifizierungsdienst in meinem GitHub-Repository erkunden. Dieses Projekt stellt verschiedene Funktionen wie Benutzerregistrierung, Anmeldung und sicheren Zugriff mithilfe von JWT zur Authentifizierung vor. Probieren Sie es einfach aus, tragen Sie dazu bei oder nutzen Sie es als Referenz für Ihre eigenen Projekte!

GitHub-Repository: https://github.com/ishrivasayush/user-auth-service

Für diejenigen, die tiefer in JSON Web Tokens (JWT) eintauchen möchten, empfehle ich den Besuch von jwt.io. Diese Ressource bietet umfassende Informationen über JWT, einschließlich seiner Funktionsweise, seiner Struktur und praktischen Beispielen. Es ist ein hervorragender Ausgangspunkt für das Verständnis der tokenbasierten Authentifizierung und Autorisierung, die für moderne Webanwendungen unerlässlich sind. Egal, ob Sie Einsteiger sind oder Ihr Wissen auffrischen möchten, jwt.io bietet wertvolle Einblicke in die sichere Verwaltung von Benutzersitzungen.

Das obige ist der detaillierte Inhalt vonMicroservices mit Spring Security sichern: JWT implementieren. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
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