# File Upload Validation

Ensuring the security of file uploads is crucial for protecting applications from malicious content. **Validating file content using file signatures** is a robust method to achieve this. File signatures, or magic numbers, are unique identifiers found at the beginning of files that indicate their type. By verifying these signatures during the upload process, we can ensure that the files are what they claim to be and not harmful.

Spring Security can be integrated with custom logic to achieve this. Here’s an example of how to validate file content using file signatures in a Spring Boot application.

## Step-by-Step Implementation:

1. **Add Dependencies:** Make sure to include the necessary dependencies in your `pom.xml` for Spring Boot and Spring Security.

   ```xml
   <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-web</artifactId>
   </dependency>
   <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-security</artifactId>
   </dependency>
   ```
2. **File Signature Checker Utility:** Create a utility class to check the file signatures. This example uses common file types like PDF, PNG, JPG, and others.

   ```java
   import java.io.IOException;
   import java.io.InputStream;
   import java.util.HashMap;
   import java.util.Map;

   public class FileSignatureChecker {

       private static final Map<String, String> FILE_SIGNATURES = new HashMap<>();

       static {
           FILE_SIGNATURES.put("25504446", "pdf"); // PDF
           FILE_SIGNATURES.put("89504E47", "png"); // PNG
           FILE_SIGNATURES.put("FFD8FF", "jpg"); // JPEG
           FILE_SIGNATURES.put("504B0304", "zip"); // ZIP
           FILE_SIGNATURES.put("47494638", "gif"); // GIF
           FILE_SIGNATURES.put("49492A00", "tiff"); // TIFF
           FILE_SIGNATURES.put("424D", "bmp"); // BMP
           FILE_SIGNATURES.put("52617221", "rar"); // RAR
           FILE_SIGNATURES.put("494433", "mp3"); // MP3
           FILE_SIGNATURES.put("52494646", "wav"); // WAV, AVI
           FILE_SIGNATURES.put("00000018", "mp4"); // MP4
           FILE_SIGNATURES.put("00000020", "mov"); // MOV
           // Add more file signatures as needed
       }

       public static String getFileType(InputStream inputStream) throws IOException {
           byte[] bytes = new byte[8];
           inputStream.read(bytes, 0, bytes.length);
           StringBuilder builder = new StringBuilder();
           for (byte b : bytes) {
               builder.append(String.format("%02X", b));
           }
           String fileSignature = builder.toString();
           for (Map.Entry<String, String> entry : FILE_SIGNATURES.entrySet()) {
               if (fileSignature.startsWith(entry.getKey())) {
                   return entry.getValue();
               }
           }
           return "unknown";
       }
   }

   ```
3. **Controller to Handle File Upload:** Create a controller to handle file upload and validate the file content.

   ```java
   import org.springframework.http.HttpStatus;
   import org.springframework.http.ResponseEntity;
   import org.springframework.security.access.annotation.Secured;
   import org.springframework.web.bind.annotation.PostMapping;
   import org.springframework.web.bind.annotation.RequestParam;
   import org.springframework.web.bind.annotation.RestController;
   import org.springframework.web.multipart.MultipartFile;

   import java.io.IOException;

   @RestController
   public class FileUploadController {

       @PostMapping("/upload")
       @Secured("ROLE_USER")
       public ResponseEntity<String> uploadFile(@RequestParam("file") MultipartFile file) {
           try (InputStream inputStream = file.getInputStream()) {
               String fileType = FileSignatureChecker.getFileType(inputStream);
               if ("unknown".equals(fileType)) {
                   return ResponseEntity.status(HttpStatus.UNSUPPORTED_MEDIA_TYPE)
                           .body("Unsupported file type");
               }
               // Process the file based on its type
               return ResponseEntity.ok("File uploaded successfully: " + fileType);
           } catch (IOException e) {
               return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                       .body("Error processing file");
           }
       }
   }
   ```
4. **Security Configuration:** Configure Spring Security to secure your file upload endpoint.

   ```java
   import org.springframework.context.annotation.Configuration;
   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.configuration.WebSecurityConfigurerAdapter;

   @Configuration
   @EnableWebSecurity
   public class SecurityConfig extends WebSecurityConfigurerAdapter {

       @Override
       protected void configure(HttpSecurity http) throws Exception {
           http
               .authorizeRequests()
               .antMatchers("/upload").authenticated()
               .and()
               .csrf().disable(); // Disable CSRF for simplicity
       }
   }
   ```

This example demonstrates how to validate file content during upload by checking file signatures with Spring Security. Adjust and expand the `FileSignatureChecker` class to include more file types as needed. Remember to handle security concerns like CSRF and authentication according to your application’s requirements.
