Authentication & Authorization with Spring Boot -Understanding “@PreAuthorize” Annotation
What are these things? Let’s explore!
- Authentication: This is the process of verifying the identity of a user or system. In Spring Security, authentication involves checking the credentials (like username and password) against a database or another user store to ensure they are valid.
- Authorization: Once a user is authenticated, authorization determines what actions or resources the authenticated user is permitted to access. It’s about managing permissions and access control.
- Verification: This term is often used interchangeably with authentication but can also refer to additional checks or validations, such as verifying the roles or permissions associated with a user.
Using Spring Security with @PreAuthorize
@PreAuthorize
is an annotation provided by Spring Security that allows you to specify access control rules at the method level. This is useful for enforcing authorization checks based on roles, permissions, or custom logic.
Here’s a step-by-step guide to setting up and using @PreAuthorize
in a Spring Boot application:
1. Add Dependencies
Ensure you have the necessary dependencies in your pom.xml
(for Maven) or build.gradle
(for Gradle).
for Maven;
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
For Gradle;
implementation ‘org.springframework.boot:spring-boot-starter-security’
2. Configure Security
Create a security configuration class that extends WebSecurityConfigurerAdapter
(or use the new style if you are using Spring Boot 3.x).
Example configuration:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true) // Enable @PreAuthorize
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated() // All requests require authentication
.and()
.formLogin(); // Use form-based login
}
}
3. Add @PreAuthorize
to Methods
Use @PreAuthorize
on your service methods or controller methods to enforce authorization rules. You can specify roles, permissions, or expressions.
Example service:
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;
@Service
public class UserService {
@PreAuthorize("hasRole('ROLE_ADMIN')")
public void performAdminTask() {
// Task that only admin can perform
}
@PreAuthorize("hasAuthority('SCOPE_read')")
public void performScopedRead() {
// Task that requires read scope
}
@PreAuthorize("#username == authentication.name")
public void updateUserProfile(String username) {
// Allow users to update their own profile only
}
}
4. Testing Security
Make sure to test your application to verify that the security rules are enforced correctly. You can write integration tests using tools like Spring Boot Test with MockMvc or use a testing framework like JUnit or TestNG.
Example test:
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.web.servlet.MockMvc;
@WebMvcTest
public class UserServiceTest {
@Autowired
private MockMvc mockMvc;
@Test
@WithMockUser(username = "admin", roles = {"ADMIN"})
public void testAdminTask() throws Exception {
mockMvc.perform(get("/admin-task"))
.andExpect(status().isOk());
}
}
In this example, @WithMockUser
is used to simulate an authenticated user with the specified role for testing purposes.
Using @PreAuthorize
, you can define method-level security rules based on roles, permissions, or custom logic. Ensure that your security configuration is set up to enable method security with @EnableGlobalMethodSecurity(prePostEnabled = true)
.
In another article I have published, I am doing a case study on this topic.If you are interested, please visit this link and complete the training!
Here it’s ; Let’s Focus on Role-Based Authorization in Spring Boot -with an Example Tiny Project
I hope it will be useful for you.
Don’t forget to follow me, your support and feedback are very important forme, Thanks..LinkedIn: https://www.linkedin.com/in/inci-kucuk
GitHub: https://github.com/incikucuk
Delightful encodings!