Skip to content

Commit

Permalink
Spring security 6 and Third party APIs added
Browse files Browse the repository at this point in the history
  • Loading branch information
ZuhriddinHere committed Apr 29, 2024
1 parent a28125a commit c2ad731
Show file tree
Hide file tree
Showing 26 changed files with 939 additions and 51 deletions.
82 changes: 80 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@
<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.0.4</version>
<relativePath/> <!-- lookup parent from repository -->
<relativePath/>
</parent>

<groupId>Team</groupId>
<artifactId>AgainSortTask</artifactId>
<version>0.0.1-SNAPSHOT</version>
Expand All @@ -16,22 +18,98 @@
<properties>
<java.version>17</java.version>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>jakarta.persistence</groupId>
<artifactId>jakarta.persistence-api</artifactId>
<version>3.2.0-M2</version>
</dependency>


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

<dependency>
<groupId>com.opencsv</groupId>
<artifactId>opencsv</artifactId>
<version>5.6</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.5</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.5</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.5</version>
</dependency>

<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.5.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.32</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.7.3</version>
</dependency>
<dependency>
<groupId>org.hibernate.orm</groupId>
<artifactId>hibernate-core</artifactId>
<version>7.0.0.Alpha1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.projectlombok</groupId>-->
<!-- <artifactId>lombok</artifactId>-->
<!-- <version>1.18.32</version>-->
<!-- <scope>provided</scope>-->
<!-- </dependency>-->

<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>

<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>

<build>
Expand All @@ -43,4 +121,4 @@
</plugins>
</build>

</project>
</project>
30 changes: 0 additions & 30 deletions src/main/java/zuhriddinscode/CsvData.java

This file was deleted.

10 changes: 7 additions & 3 deletions src/main/java/zuhriddinscode/TeamApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,18 @@

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
public class TeamApplication {

public static void main(String[] args) {
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
};

public static void main(String[] args) {
SpringApplication.run(TeamApplication.class, args);

}

}
70 changes: 70 additions & 0 deletions src/main/java/zuhriddinscode/config/JwtAuthenticationFilter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package zuhriddinscode.config;

import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.lang.NonNull;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import zuhriddinscode.service.JwtService;
import zuhriddinscode.service.UserService;

import java.io.IOException;

@Component
@RequiredArgsConstructor
public class JwtAuthenticationFilter extends OncePerRequestFilter {
public static final String BEARER_PREFIX = "Bearer ";
public static final String HEADER_NAME = "Authorization";
private final JwtService jwtService;
private final UserService userService;

@Override
protected void doFilterInternal(
@NonNull HttpServletRequest request,
@NonNull HttpServletResponse response,
@NonNull FilterChain filterChain
) throws ServletException, IOException {

// Получаем токен из заголовка
var authHeader = request.getHeader(HEADER_NAME);
if (StringUtils.isEmpty(authHeader) || !StringUtils.startsWith(authHeader, BEARER_PREFIX)) {
filterChain.doFilter(request, response);
return;
}

// Обрезаем префикс и получаем имя пользователя из токена
var jwt = authHeader.substring(BEARER_PREFIX.length());
var username = jwtService.extractUserName(jwt);

if (StringUtils.isNotEmpty(username) && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = userService
.userDetailsService()
.loadUserByUsername(username);

// Если токен валиден, то аутентифицируем пользователя
if (jwtService.isTokenValid(jwt, userDetails)) {
SecurityContext context = SecurityContextHolder.createEmptyContext();

UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(
userDetails,
null,
userDetails.getAuthorities()
);

authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
context.setAuthentication(authToken);
SecurityContextHolder.setContext(context);
}
}
filterChain.doFilter(request, response);
}
}
77 changes: 77 additions & 0 deletions src/main/java/zuhriddinscode/config/SecurityConfiguration.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package zuhriddinscode.config;

import lombok.RequiredArgsConstructor;
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.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 zuhriddinscode.service.UserService;

import java.util.List;

import static org.springframework.security.config.http.SessionCreationPolicy.STATELESS;

@Configuration
@EnableWebSecurity
@EnableMethodSecurity
@RequiredArgsConstructor
public class SecurityConfiguration {

private final JwtAuthenticationFilter jwtAuthenticationFilter;
private final UserService userService;

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.csrf(AbstractHttpConfigurer::disable)
// Своего рода отключение CORS (разрешение запросов со всех доменов)
.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
// Можно указать конкретный путь, * - 1 уровень вложенности, ** - любое количество уровней вложенности
.requestMatchers("/auth/**").permitAll()
.requestMatchers("/swagger-ui/**", "/swagger-resources/*", "/v3/api-docs/**").permitAll()
.requestMatchers("/endpoint", "/admin/**").hasRole("ADMIN")
.anyRequest().authenticated())
.sessionManagement(manager -> manager.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();
}
}
35 changes: 35 additions & 0 deletions src/main/java/zuhriddinscode/controller/AuthController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package zuhriddinscode.controller;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
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;
import zuhriddinscode.domain.dto.JwtAuthenticationResponse;
import zuhriddinscode.domain.dto.SignInRequest;
import zuhriddinscode.domain.dto.SignUpRequest;
import zuhriddinscode.service.AuthenticationService;

@RestController
@RequestMapping("/auth")
@RequiredArgsConstructor
@Tag(name = "Аутентификация")
public class AuthController {

private final AuthenticationService authenticationService;

@Operation(summary = "Регистрация пользователя")
@PostMapping("/sign-up")
public JwtAuthenticationResponse signUp(@RequestBody @Valid SignUpRequest request) {
return authenticationService.signUp(request);
}

@Operation(summary = "Авторизация пользователя")
@PostMapping("/sign-in")
public JwtAuthenticationResponse signIn(@RequestBody @Valid SignInRequest request) {
return authenticationService.signIn(request);
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package zuhriddinscode;
package zuhriddinscode.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import zuhriddinscode.domain.model.CsvData;
import zuhriddinscode.service.CsvService;

import java.io.BufferedReader;
import java.io.InputStreamReader;
Expand All @@ -16,9 +18,9 @@ public class CsvController {
private CsvService csvService;

@PostMapping("/upload")
public List<CsvData> uploadAndSortCsv
( @RequestParam("file") MultipartFile file,
@RequestParam(required = false, defaultValue = "numeric") String sortType ) throws Exception {
public List<CsvData> uploadAndSortCsv ( @RequestParam("file") MultipartFile file,
@RequestParam(required = false, defaultValue = "numeric") String sortType )
throws Exception {

BufferedReader reader =
new BufferedReader
Expand All @@ -32,7 +34,4 @@ public class CsvController {
return csvService.sortDataAlphabetically(data);
}
}



}
Loading

0 comments on commit c2ad731

Please sign in to comment.