1. Introduction
Input validation and authorization are two critical pillars of secure backend application development. In Spring Boot, these capabilities can be implemented cleanly using built-in annotations such as @Valid, JSR-380 validation constraints (@NotNull, @Size, @Email, etc.), and Spring Security annotations (@PreAuthorize, @Secured). This article demonstrates how these annotations work together to ensure that only valid data enters your system and that only authorized users can perform restricted operations.
2. Problem
Without proper validation and security, your application becomes vulnerable to several issues:
- Invalid or malicious data entering the system, leading to runtime errors or data corruption.
- Bypassing business rules such as missing required fields or improper formatting (e.g., invalid email).
- Unauthorized access to APIs, where users without the proper roles can perform restricted actions.
A robust design must enforce validation rules at the API layer and restrict sensitive endpoints based on user roles.
3. Solution
Spring Boot solves these challenges with two powerful features:
3.1 Request Validation
@Validor@Validated— triggers validation on incoming request bodies or parameters.- JSR-380 annotations such as:
@NotNull— ensures the field is not null@Size— enforces length restrictions@Email— enforces correct email formatting
3.2 Method-Level Security
@PreAuthorize— allows SpEL expressions likehasRole('ADMIN')@Secured— simple role-based access control
Using these annotations together ensures data is validated before business logic executes and that sensitive operations are protected from unauthorized access.
4. Implementation
Below is a complete implementation example demonstrating validation and security features inside a Spring Boot REST API.
4.1 Add Dependencies (pom.xml)
<dependencies>
<!-- Spring Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Validation (JSR 380) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!-- Spring Security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
</dependencies>4.2 Enable Method-Level Security
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
@Configuration
@EnableMethodSecurity
public class SecurityConfig {
}4.3 Create a DTO with Validation Rules
import javax.validation.constraints.Email;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
public class UserRequest {
@NotNull(message = "Name is required")
@Size(min = 2, max = 50, message = "Name must be between 2 and 50 characters")
private String name;
@NotNull(message = "Email is required")
@Email(message = "Email format is invalid")
private String email;
@NotNull(message = "Password is required")
@Size(min = 8, message = "Password must be at least 8 characters long")
private String password;
// getters and setters
}4.4 Create a Secured Service Layer
import org.springframework.security.access.annotation.Secured;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;
@Service
public class UserService {
@PreAuthorize("hasRole('ADMIN')")
public String createUser(UserRequest request) {
return "User created: " + request.getEmail();
}
@Secured("ROLE_USER")
public String getUserProfile(String email) {
return "Profile for: " + email;
}
}4.5 Create the Controller with @Valid
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
@RestController
@RequestMapping("/api/users")
@Validated
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
@PostMapping
public String createUser(@Valid @RequestBody UserRequest request) {
return userService.createUser(request);
}
@GetMapping("/{email}")
public String getProfile(@PathVariable("email") String email) {
return userService.getUserProfile(email);
}
}4.6 Example Validation Error Response
{
"timestamp": "2025-11-24T20:00:00",
"status": 400,
"errors": [
"Name must be between 2 and 50 characters",
"Email format is invalid",
"Password must be at least 8 characters long"
]
}4.7 Example Security Behavior
- A user without ADMIN role calling
POST /api/users→ HTTP 403 Forbidden - A user with USER role calling
GET /api/users/{email}→ Success - A user with no roles calling either endpoint → HTTP 403 Forbidden
5. Conclusion
Validation and security are essential components of a well-designed Spring Boot application. Using annotations such as @Valid, @NotNull, @Email, @PreAuthorize, and @Secured, developers can easily enforce strict data integrity and apply precise access control policies. This approach reduces boilerplate code, increases maintainability, and protects your application from invalid input and unauthorized access.