@PreAuthorize is a part of Spring Security’s method-level security framework. It allows specifying authorization logic directly on methods in controller or service classes using SpEL-based expressions.
The @PreAuthorize annotation works by evaluating a Spring Expression Language (SpEL) expression before executing the target method. If the expression evaluates to false, Spring Security throws an AccessDeniedException, preventing the method from running.
Example Definition:
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface PreAuthorize {
String value();
}
The value attribute accepts a SpEL expression that defines the security condition.
Common Use Cases
- Restricting access based on roles or authorities.
- Ensuring only authenticated users can access certain methods.
- Controlling access dynamically using custom user attributes or method parameters.
Understanding SpEL (Spring Expression Language) in @PreAuthorize
SpEL enables writing flexible access control expressions. Common usage examples include:
- hasRole('ROLE_ADMIN'): Grants access only to users having the specified role
- hasAuthority('READ_PRIVILEGE'): Checks whether the user has a specific authority
- isAuthenticated(): Ensures the user is authenticated (logged in)
- #id == authentication.principal.id: Allows access only when the resource belongs to the currently logged-in user
How @PreAuthorize Works
When a method annotated with @PreAuthorize is invoked, Spring Security follows this flow:
1. User Authentication: The user is authenticated by Spring Security.
2. Expression Evaluation: The SpEL expression defined in the annotation is evaluated using the user’s roles, authorities, or authentication object.
3. Access Decision:
- If the condition returns true, the method executes.
- If false, an AccessDeniedException is thrown.
Implementation of @PreAuthorize in Spring Boot
Below is a step-by-step guide to implementing method-level security using @PreAuthorize in a Spring Boot application.
Step 1: Create a Spring Boot Project
Create a new Spring Boot project using Maven with the following options:
- Name: spring-security-preauthorize
- Dependencies: Spring Web, Spring Security, Lombok, DevTools

Step 2: Add Dependencies
Your pom.xml file should include:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
Project Structure

Step 3: Configure Application Properties
spring.application.name=spring-security-preauthorize
Step 4: Create the User Class
package com.gfg.springsecuritypreauthorize;
public class User {
private Long id;
private String username;
private String role;
public User(Long id, String username, String role) {
this.id = id;
this.username = username;
this.role = role;
}
public Long getId() {
return id;
}
public String getUsername() {
return username;
}
public String getRole() {
return role;
}
}
This simple User class models a user entity with fields for ID, username, and role.
Step 5: Create the UserService Class
package com.gfg.springsecuritypreauthorize;
import org.springframework.stereotype.Service;
@Service
public class UserService {
// Returns a mock user
public User getUser() {
return new User(1L, "John Doe", "ROLE_USER");
}
}
This service returns a mock user for demonstration. In real-world scenarios, it would fetch user data from a database.
Step 6: Configure Spring Security
package com.gfg.springsecuritypreauthorize;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
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.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
@EnableWebSecurity
@EnableMethodSecurity(prePostEnabled = true)
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf.disable())
.authorizeHttpRequests(auth -> auth
.requestMatchers("/user").hasRole("USER")
.anyRequest().authenticated())
.httpBasic();
return http.build();
}
@Bean
public AuthenticationManager authManager(HttpSecurity http) throws Exception {
AuthenticationManagerBuilder builder = http.getSharedObject(AuthenticationManagerBuilder.class);
builder.inMemoryAuthentication()
.withUser("user")
.password(passwordEncoder().encode("password"))
.roles("USER");
return builder.build();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
- @EnableMethodSecurity(prePostEnabled = true) enables method-level annotations like @PreAuthorize.
- A simple in-memory user user/password with role USER is configured.
- Basic authentication is used for simplicity.
Step 7: Create the UserController Class
package com.gfg.springsecuritypreauthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
@Autowired
private UserService userService;
// Accessible only to users with ROLE_USER
@PreAuthorize("hasRole('ROLE_USER')")
@GetMapping("/user")
public User getUser() {
return userService.getUser();
}
}
The @PreAuthorize("hasRole('ROLE_USER')") annotation ensures that only users with the role ROLE_USER can access the /user endpoint. If an unauthorized user attempts to call this method, an AccessDeniedException will be thrown.
Step 8: Main Application Class
package com.gfg.springsecuritypreauthorize;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringSecurityPreauthorizeApplication {
public static void main(String[] args) {
SpringApplication.run(SpringSecurityPreauthorizeApplication.class, args);
}
}
Step 9: Run the Application
Run the application using your IDE or Maven:

By default, it runs on port 8080.
Step 10: Testing the Application
Use Basic Authentication to test the secured endpoint.
Request:
GET: http://localhost:8080/user
Credentials:
- Username: user
- Password: password
Response:

If you try to access the endpoint without valid credentials or roles, you’ll receive Access Denied.