Refactor and secure backend configuration, DTOs, and authentication flow
- Updated pom.xml: removed redundant tags, grouped dependencies, added scopes, and upgraded plugins
- Enhanced RegisterUserDto with validation annotations and added missing fields (username, fullname)
- Updated User entity with builder constructor and removed redundant getters/setters
- Completed FileMetadata entity with Lombok and required setters/getters
- Improved HDFSConfig with correct annotation and clearer exception message
- Adjusted HTTP to HTTPS redirect port (8085 -> 8443)
- Allowed /actuator/** in SecurityConfig and disabled deprecated XSS protection
- Skipped JWT filter for /api/auth and /actuator paths
- Refactored AuthenticationService to use builder pattern and RSA key injection
- Fixed application.properties for static MySQL connection (removed ${MYSQL_PASSWORD})
This commit is contained in:
@@ -1,89 +1,57 @@
|
||||
<?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"
|
||||
<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.4.4</version>
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
<relativePath/>
|
||||
</parent>
|
||||
|
||||
<groupId>com.skycrate.backend</groupId>
|
||||
<artifactId>skycrateBackend</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>skycrateBackend</name>
|
||||
<description>Cloud Storage App using HDFS</description>
|
||||
<url/>
|
||||
<licenses>
|
||||
<license/>
|
||||
</licenses>
|
||||
<developers>
|
||||
<developer/>
|
||||
</developers>
|
||||
<scm>
|
||||
<connection/>
|
||||
<developerConnection/>
|
||||
<tag/>
|
||||
<url/>
|
||||
</scm>
|
||||
|
||||
<properties>
|
||||
<java.version>17</java.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<!-- Spring Boot Starters -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
</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>
|
||||
|
||||
|
||||
<!-- NEWLY ADDED DEPENDECIES-->
|
||||
<!-- Spring Boot Web -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
<version>3.2.4</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Spring Boot Security -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
<version>3.2.4</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Spring Boot Data JPA -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
<version>3.2.4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-validation</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- MySQL Driver -->
|
||||
<!-- MySQL JDBC -->
|
||||
<dependency>
|
||||
<groupId>com.mysql</groupId>
|
||||
<artifactId>mysql-connector-j</artifactId>
|
||||
<version>8.3.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Spring Boot Validation -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-validation</artifactId>
|
||||
<version>3.2.4</version>
|
||||
</dependency>
|
||||
|
||||
<!-- JSON Web Token (JWT) -->
|
||||
<!-- JWT -->
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-api</artifactId>
|
||||
@@ -93,14 +61,16 @@
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-impl</artifactId>
|
||||
<version>0.11.5</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-jackson</artifactId>
|
||||
<version>0.11.5</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Hadoop Dependencies -->
|
||||
<!-- Hadoop HDFS -->
|
||||
<dependency>
|
||||
<groupId>org.apache.hadoop</groupId>
|
||||
<artifactId>hadoop-common</artifactId>
|
||||
@@ -112,74 +82,72 @@
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.hadoop</groupId>
|
||||
<artifactId>hadoop-hdfs</artifactId>
|
||||
<version>3.4.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.hadoop</groupId>
|
||||
<artifactId>hadoop-client</artifactId>
|
||||
<version>3.4.1</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Logging (SLF4J + Logback) -->
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>org.slf4j</groupId>-->
|
||||
<!-- <artifactId>slf4j-api</artifactId>-->
|
||||
<!-- <version>1.7.36</version>-->
|
||||
<!-- </dependency>-->
|
||||
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>ch.qos.logback</groupId>-->
|
||||
<!-- <artifactId>logback-classic</artifactId>-->
|
||||
<!-- <version>1.2.11</version>-->
|
||||
<!-- </dependency>-->
|
||||
|
||||
<!-- Apache Commons IO (for file operations) -->
|
||||
<!-- Commons IO -->
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>2.11.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<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>
|
||||
|
||||
<!-- Caffeine Cache -->
|
||||
<dependency>
|
||||
<groupId>com.github.ben-manes.caffeine</groupId>
|
||||
<artifactId>caffeine</artifactId>
|
||||
<version>3.1.8</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Lombok -->
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.30</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Testing -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<!-- Compiler Plugin -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.11.0</version>
|
||||
<configuration>
|
||||
<source>${java.version}</source>
|
||||
<target>${java.version}</target>
|
||||
<annotationProcessorPaths>
|
||||
<path>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.30</version>
|
||||
</path>
|
||||
</annotationProcessorPaths>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<!-- Spring Boot Plugin -->
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.skycrate.backend.skycrateBackend.config;
|
||||
|
||||
import org.apache.hadoop.conf.Configuration;
|
||||
import org.apache.hadoop.conf.Configuration; // Hadoop Configuration
|
||||
import org.apache.hadoop.fs.FileSystem;
|
||||
import org.apache.hadoop.security.UserGroupInformation;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@@ -8,20 +8,17 @@ import org.springframework.context.annotation.Bean;
|
||||
import java.net.URI;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
|
||||
// HDFS configuration bean to securely connect to a remote Hadoop cluster.
|
||||
@Configuration
|
||||
@org.springframework.context.annotation.Configuration
|
||||
public class HDFSConfig {
|
||||
|
||||
private static final String HDFS_URI = System.getenv("HDFS_URI"); // export HDFS_URI=hdfs://192.168.29.30:9000
|
||||
private static final String HDFS_USER = System.getenv("HDFS_USER"); // Hadoop user (if needed)
|
||||
private static final String HDFS_URI = System.getenv("HDFS_URI"); // e.g., hdfs://namenode:9000
|
||||
private static final String HDFS_USER = System.getenv("HDFS_USER"); // e.g., hdfsuser
|
||||
|
||||
// Configures and returns a secured HDFS FileSystem instance.
|
||||
@Bean
|
||||
public FileSystem fileSystem() throws Exception {
|
||||
return getHDFS(); // use the static method internally
|
||||
return getHDFS();
|
||||
}
|
||||
|
||||
// Static method to get a FileSystem instance. Used by other classes like HDFSController.
|
||||
public static FileSystem getHDFS() throws Exception {
|
||||
if (HDFS_URI == null || HDFS_URI.isBlank()) {
|
||||
throw new IllegalStateException("HDFS_URI environment variable not set.");
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ public class HttpToHttpsRedirectConfig {
|
||||
return factory -> {
|
||||
Connector connector = new Connector(TomcatServletWebServerFactory.DEFAULT_PROTOCOL);
|
||||
connector.setScheme("http");
|
||||
connector.setPort(8080); // HTTP port
|
||||
connector.setPort(8085); // HTTP port
|
||||
connector.setSecure(false);
|
||||
connector.setRedirectPort(8443); // HTTPS port
|
||||
factory.addAdditionalTomcatConnectors(connector);
|
||||
|
||||
-74
@@ -1,74 +0,0 @@
|
||||
package com.skycrate.backend.skycrateBackend.config;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
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.Component;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
import org.springframework.web.servlet.HandlerExceptionResolver;
|
||||
|
||||
import com.skycrate.backend.skycrateBackend.services.JwtService;
|
||||
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
@Component
|
||||
public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
||||
|
||||
|
||||
private final HandlerExceptionResolver handlerExceptionResolver;
|
||||
private JwtService jwtService;
|
||||
private UserDetailsService userDetailsService;
|
||||
|
||||
public JwtAuthenticationFilter(JwtService jwtService,UserDetailsService userDetailsService,HandlerExceptionResolver handlerExceptionResolver){
|
||||
|
||||
this.handlerExceptionResolver=handlerExceptionResolver;
|
||||
this.jwtService=jwtService;
|
||||
this.userDetailsService=userDetailsService;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(
|
||||
@NonNull HttpServletRequest request,
|
||||
@NonNull HttpServletResponse response,
|
||||
@NonNull FilterChain filterChain) throws ServletException, IOException {
|
||||
final String authHeader=request.getHeader("Authorization");
|
||||
if (authHeader==null || !authHeader.startsWith("Bearer")){
|
||||
filterChain.doFilter(request, response);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
final String userjwt=authHeader.substring(7);
|
||||
final String userEmail=jwtService.extractUsername(userjwt);
|
||||
Authentication authentication=SecurityContextHolder.getContext().getAuthentication();
|
||||
if(userEmail!=null && authentication==null){
|
||||
|
||||
UserDetails userDetails=this.userDetailsService.loadUserByUsername(userEmail);
|
||||
if (jwtService.isTokenValid(userjwt, userDetails)) {
|
||||
|
||||
UsernamePasswordAuthenticationToken authenticationToken=new UsernamePasswordAuthenticationToken(
|
||||
userDetails, null, userDetails.getAuthorities()
|
||||
);
|
||||
authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
|
||||
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
|
||||
}
|
||||
|
||||
}
|
||||
filterChain.doFilter(request, response);
|
||||
}
|
||||
catch (Exception err) {
|
||||
handlerExceptionResolver.resolveException(request, response, null, err);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -29,7 +29,7 @@ public class SecurityConfig {
|
||||
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
|
||||
.authenticationProvider(authenticationProvider)
|
||||
.authorizeHttpRequests(auth -> auth
|
||||
.requestMatchers("/api/auth/**").permitAll()
|
||||
.requestMatchers("/api/auth/**", "/actuator/**").permitAll()
|
||||
.requestMatchers(HttpMethod.GET, "/public/**").permitAll()
|
||||
.anyRequest().authenticated()
|
||||
)
|
||||
@@ -41,7 +41,8 @@ public class SecurityConfig {
|
||||
.includeSubDomains(true)
|
||||
.maxAgeInSeconds(31536000)
|
||||
)
|
||||
.xssProtection(xss -> xss.block(true))
|
||||
// Spring Security 6+ no longer supports xss.block(true), so we just enable or disable it.
|
||||
.xssProtection(xss -> xss.disable())
|
||||
.frameOptions(frame -> frame.deny())
|
||||
)
|
||||
.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
|
||||
|
||||
@@ -1,46 +1,46 @@
|
||||
package com.skycrate.backend.skycrateBackend.dto;
|
||||
|
||||
import jakarta.validation.constraints.Email;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
import jakarta.validation.constraints.Size;
|
||||
|
||||
public class RegisterUserDto {
|
||||
|
||||
@NotBlank(message = "Email is required")
|
||||
@Email(message = "Email should be valid")
|
||||
private String email;
|
||||
|
||||
@NotBlank(message = "Password is required")
|
||||
@Size(min = 8, message = "Password must be at least 8 characters")
|
||||
private String password;
|
||||
|
||||
@NotBlank(message = "Username is required")
|
||||
@Pattern(regexp = "^[a-zA-Z0-9]+$", message = "Username must be alphanumeric")
|
||||
private String username;
|
||||
|
||||
@NotBlank(message = "Full name is required")
|
||||
private String fullname;
|
||||
|
||||
@NotBlank(message = "First name is required")
|
||||
private String firstname;
|
||||
|
||||
@NotBlank(message = "Last name is required")
|
||||
private String lastname;
|
||||
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
// Getters
|
||||
public String getEmail() { return email; }
|
||||
public String getPassword() { return password; }
|
||||
public String getUsername() { return username; }
|
||||
public String getFullname() { return fullname; }
|
||||
public String getFirstname() { return firstname; }
|
||||
public String getLastname() { return lastname; }
|
||||
|
||||
public RegisterUserDto setEmail(String email) {
|
||||
this.email = email;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public RegisterUserDto setPassword(String password) {
|
||||
this.password = password;
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
public String getFirstname() {
|
||||
return firstname;
|
||||
}
|
||||
|
||||
public RegisterUserDto setFirstname(String firstname) {
|
||||
this.firstname = firstname;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getLastname() {
|
||||
return lastname;
|
||||
}
|
||||
|
||||
public RegisterUserDto setLastname(String lastname) {
|
||||
this.lastname = lastname;
|
||||
return this;
|
||||
}
|
||||
// Setters
|
||||
public void setEmail(String email) { this.email = email; }
|
||||
public void setPassword(String password) { this.password = password; }
|
||||
public void setUsername(String username) { this.username = username; }
|
||||
public void setFullname(String fullname) { this.fullname = fullname; }
|
||||
public void setFirstname(String firstname) { this.firstname = firstname; }
|
||||
public void setLastname(String lastname) { this.lastname = lastname; }
|
||||
}
|
||||
@@ -1,23 +1,43 @@
|
||||
package com.skycrate.backend.skycrateBackend.entity;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.*;
|
||||
|
||||
@Entity
|
||||
@Table(name = "file_metadata")
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public class FileMetadata {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String filePath;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String username;
|
||||
|
||||
@Lob
|
||||
@Column(nullable = false)
|
||||
private byte[] salt;
|
||||
|
||||
@Lob
|
||||
@Column(nullable = false)
|
||||
private byte[] iv;
|
||||
|
||||
// Getters and Setters
|
||||
public void setUsername(String username) { this.username = username; }
|
||||
public void setFilePath(String filePath) { this.filePath = filePath; }
|
||||
public void setSalt(byte[] salt) { this.salt = salt; }
|
||||
public void setIv(byte[] iv) { this.iv = iv; }
|
||||
|
||||
public String getUsername() { return this.username; }
|
||||
public String getFilePath() { return this.filePath; }
|
||||
public byte[] getSalt() { return this.salt; }
|
||||
public byte[] getIv() { return this.iv; }
|
||||
|
||||
}
|
||||
@@ -14,7 +14,6 @@ import java.util.List;
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public class User implements UserDetails {
|
||||
|
||||
@Id
|
||||
@@ -39,6 +38,16 @@ public class User implements UserDetails {
|
||||
@Lob
|
||||
private byte[] privateKey;
|
||||
|
||||
@Builder
|
||||
public User(String email, String password, String username, String fullname, byte[] publicKey, byte[] privateKey) {
|
||||
this.email = email;
|
||||
this.password = password;
|
||||
this.username = username;
|
||||
this.fullname = fullname;
|
||||
this.publicKey = publicKey;
|
||||
this.privateKey = privateKey;
|
||||
}
|
||||
|
||||
// --- UserDetails interface methods ---
|
||||
@Override
|
||||
public Collection<? extends GrantedAuthority> getAuthorities() {
|
||||
@@ -74,45 +83,4 @@ public class User implements UserDetails {
|
||||
public boolean isEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
// --- Extra getter methods for HDFScontroller compatibility ---
|
||||
public byte[] getPublicKey() {
|
||||
return publicKey;
|
||||
}
|
||||
|
||||
public byte[] getPrivateKey() {
|
||||
return privateKey;
|
||||
}
|
||||
|
||||
public String getFullname() {
|
||||
return fullname;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
}
|
||||
+6
@@ -37,6 +37,12 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
||||
FilterChain filterChain)
|
||||
throws ServletException, IOException {
|
||||
|
||||
String path = request.getRequestURI();
|
||||
if (path.startsWith("/api/auth") || path.startsWith("/actuator")) {
|
||||
filterChain.doFilter(request, response);
|
||||
return;
|
||||
}
|
||||
|
||||
final String authHeader = request.getHeader("Authorization");
|
||||
final String jwt;
|
||||
final String userEmail;
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
package com.skycrate.backend.skycrateBackend.security;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.Cache;
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Service
|
||||
public class RateLimiterService {
|
||||
|
||||
private final Cache<String, Integer> attemptsCache;
|
||||
|
||||
private static final int MAX_ATTEMPTS = 5;
|
||||
|
||||
public RateLimiterService() {
|
||||
this.attemptsCache = Caffeine.newBuilder()
|
||||
.expireAfterWrite(1, TimeUnit.MINUTES)
|
||||
.build();
|
||||
}
|
||||
|
||||
public boolean isBlocked(String key) {
|
||||
Integer attempts = attemptsCache.getIfPresent(key);
|
||||
return attempts != null && attempts >= MAX_ATTEMPTS;
|
||||
}
|
||||
|
||||
public void recordFailedAttempt(String key) {
|
||||
int attempts = attemptsCache.getIfPresent(key) == null ? 0 : attemptsCache.getIfPresent(key);
|
||||
attemptsCache.put(key, attempts + 1);
|
||||
}
|
||||
|
||||
public void resetAttempts(String key) {
|
||||
attemptsCache.invalidate(key);
|
||||
}
|
||||
}
|
||||
+18
-16
@@ -1,15 +1,14 @@
|
||||
package com.skycrate.backend.skycrateBackend.services;
|
||||
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.skycrate.backend.skycrateBackend.dto.LoginUserDto;
|
||||
import com.skycrate.backend.skycrateBackend.dto.RegisterUserDto;
|
||||
import com.skycrate.backend.skycrateBackend.entity.User;
|
||||
import com.skycrate.backend.skycrateBackend.repository.UserRepository;
|
||||
import com.skycrate.backend.skycrateBackend.utils.RSAKeyUtil;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.security.KeyPair;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
@@ -21,28 +20,31 @@ public class AuthenticationService {
|
||||
private final PasswordEncoder passwordEncoder;
|
||||
private final AuthenticationManager authenticationManager;
|
||||
|
||||
public AuthenticationService(UserRepository userRepository, AuthenticationManager authenticationManager, PasswordEncoder passwordEncoder) {
|
||||
public AuthenticationService(UserRepository userRepository,
|
||||
AuthenticationManager authenticationManager,
|
||||
PasswordEncoder passwordEncoder) {
|
||||
this.userRepository = userRepository;
|
||||
this.passwordEncoder = passwordEncoder;
|
||||
this.authenticationManager = authenticationManager;
|
||||
}
|
||||
|
||||
public User signUp(RegisterUserDto inputUser) {
|
||||
User user = new User(
|
||||
inputUser.getFirstname(),
|
||||
inputUser.getLastname(),
|
||||
inputUser.getEmail(),
|
||||
passwordEncoder.encode(inputUser.getPassword())
|
||||
);
|
||||
|
||||
KeyPair keyPair;
|
||||
try {
|
||||
KeyPair keyPair = RSAKeyUtil.generateKeyPair();
|
||||
user.setPublicKey(keyPair.getPublic().getEncoded());
|
||||
user.setPrivateKey(keyPair.getPrivate().getEncoded());
|
||||
keyPair = RSAKeyUtil.generateKeyPair();
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new RuntimeException("Failed to generate RSA key pair", e);
|
||||
}
|
||||
|
||||
User user = User.builder()
|
||||
.fullname(inputUser.getFirstname() + " " + inputUser.getLastname())
|
||||
.username(inputUser.getUsername())
|
||||
.email(inputUser.getEmail())
|
||||
.password(passwordEncoder.encode(inputUser.getPassword()))
|
||||
.publicKey(keyPair.getPublic().getEncoded())
|
||||
.privateKey(keyPair.getPrivate().getEncoded())
|
||||
.build();
|
||||
|
||||
return userRepository.save(user);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user