Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Реализация бэкенда авторизации и регистрации через JWT #56

Merged
merged 15 commits into from
Dec 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 48 additions & 19 deletions backend/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,37 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</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-security</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.12.3</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.12.3</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.12.3</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
Expand All @@ -48,9 +75,8 @@
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
Expand All @@ -69,26 +95,29 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
<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>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.10</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>prepare-package</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package ru.pominov.lenka_messenger;
package ru.pominov.lenkamessenger;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package ru.pominov.lenkamessenger.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
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.config.http.SessionCreationPolicy;
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;
import org.springframework.web.cors.CorsConfiguration;
import ru.pominov.lenkamessenger.filter.JwtAuthenticationFilter;
import ru.pominov.lenkamessenger.service.user.UserService;

import java.util.List;

@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class SecurityConfiguration {

private final UserService userService;
private final JwtAuthenticationFilter jwtAuthenticationFilter;

public SecurityConfiguration(UserService userService, JwtAuthenticationFilter jwtAuthenticationFilter) {
this.userService = userService;
this.jwtAuthenticationFilter = jwtAuthenticationFilter;
}

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.csrf(AbstractHttpConfigurer::disable)
.cors(cors -> cors.configurationSource(request -> {
var corsConfiguration = new CorsConfiguration();
corsConfiguration.setAllowedOriginPatterns(List.of("*"));
corsConfiguration.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "OPTIONS"));
corsConfiguration.setAllowedHeaders(List.of("*"));
corsConfiguration.setAllowCredentials(true);
return corsConfiguration;
}))
.authorizeHttpRequests(request -> request
.requestMatchers("/auth/**").permitAll()
.anyRequest().authenticated())
.sessionManagement(manager -> manager.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authenticationProvider(authenticationProvider())
.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
return http.build();
}

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

@Bean
public AuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userService.userDetailsService());
authProvider.setPasswordEncoder(passwordEncoder());
return authProvider;
}

@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {
return config.getAuthenticationManager();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package ru.pominov.lenkamessenger.controller.auth;

import jakarta.validation.Valid;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import ru.pominov.lenkamessenger.dto.user.JwtAuthenticationResponse;
import ru.pominov.lenkamessenger.dto.user.SignInRequest;
import ru.pominov.lenkamessenger.dto.user.SignUpRequest;
import ru.pominov.lenkamessenger.service.auth.AuthenticationService;

@RestController
@RequestMapping("/auth")
public class AuthController {

private final AuthenticationService authenticationService;

public AuthController(AuthenticationService authenticationService) {
this.authenticationService = authenticationService;
}

@PostMapping("/register")
@ResponseStatus(HttpStatus.CREATED)
public JwtAuthenticationResponse signUp(@RequestBody @Valid SignUpRequest request) {
return authenticationService.signUp(request);
}

@PostMapping("/login")
public JwtAuthenticationResponse singIn(@RequestBody @Valid SignInRequest request) {
return authenticationService.signIn(request);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package ru.pominov.lenkamessenger.dto.user;

public class JwtAuthenticationResponse {

public JwtAuthenticationResponse() {}

public JwtAuthenticationResponse(String token) {
this.token = token;
}

private String token;

public String getToken() {
return token;
}

public void setToken(String token) {
this.token = token;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package ru.pominov.lenkamessenger.dto.user;

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;

import java.util.Objects;

public class SignInRequest {

public SignInRequest() {}

public SignInRequest(String username, String password) {
this.username = username;
this.password = password;
}

@NotBlank
@Size(min = 5, max = 50)
private String username;

@NotBlank
@Size(min = 8, max = 255)
private String password;

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
SignInRequest that = (SignInRequest) o;
return Objects.equals(username, that.username) && Objects.equals(password, that.password);
}

@Override
public int hashCode() {
return Objects.hash(username, password);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package ru.pominov.lenkamessenger.dto.user;

import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;

import java.util.Objects;

public class SignUpRequest {

public SignUpRequest() {}

public SignUpRequest(String username, String password, String email, String firstName, String lastName) {
this.username = username;
this.password = password;
this.email = email;
this.firstName = firstName;
this.lastName = lastName;
}

@NotBlank
@Size(min = 5, max = 50)
private String username;

@NotBlank
@Size(min = 8, max = 255)
private String password;

@NotBlank
@Email
private String email;

@NotBlank
private String firstName;

@NotBlank
private String lastName;

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

public String getEmail() {
return email;
}

public void setEmail(String email) {
this.email = email;
}

public String getFirstName() {
return firstName;
}

public void setFirstName(String firstName) {
this.firstName = firstName;
}

public String getLastName() {
return lastName;
}

public void setLastName(String lastName) {
this.lastName = lastName;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
SignUpRequest that = (SignUpRequest) o;
return Objects.equals(username, that.username) &&
Objects.equals(password, that.password) &&
Objects.equals(email, that.email) &&
Objects.equals(firstName, that.firstName) &&
Objects.equals(lastName, that.lastName);
}

@Override
public int hashCode() {
return Objects.hash(username, password, email, firstName, lastName);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package ru.pominov.lenkamessenger.exception;

public class BadRequestException extends RuntimeException {
public BadRequestException(String message) {
super(message);
}
}
Loading
Loading