javaadvanced

Spring Security — Role-Based Access Control

Configure RBAC with Spring Security: roles, method security, endpoint permissions, and custom filters.

java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.web.SecurityFilterChain;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .csrf(csrf -> csrf.disable())
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/api/public/**").permitAll()
                .requestMatchers("/api/admin/**").hasRole("ADMIN")
                .requestMatchers("/api/manager/**").hasAnyRole("ADMIN", "MANAGER")
                .requestMatchers("GET", "/api/users/**").hasAuthority("READ_USERS")
                .requestMatchers("POST", "/api/users/**").hasAuthority("CREATE_USERS")
                .requestMatchers("DELETE", "/api/users/**").hasAuthority("DELETE_USERS")
                .anyRequest().authenticated()
            )
            .httpBasic(basic -> {});

        return http.build();
    }
}

// Method-level security
@RestController
@RequestMapping("/api/users")
class UserController {

    @GetMapping
    @PreAuthorize("hasAuthority('READ_USERS')")
    public String listUsers() {
        return "User list";
    }

    @PostMapping
    @PreAuthorize("hasRole('ADMIN')")
    public String createUser() {
        return "User created";
    }

    @DeleteMapping("/{id}")
    @PreAuthorize("hasRole('ADMIN') and #id != principal.id")
    public String deleteUser(@PathVariable Long id) {
        return "User deleted: " + id;
    }

    // Custom SpEL expression
    @PutMapping("/{id}")
    @PreAuthorize("@accessChecker.canEdit(#id, principal)")
    public String updateUser(@PathVariable Long id) {
        return "User updated: " + id;
    }
}

// Custom access checker bean
@org.springframework.stereotype.Component("accessChecker")
class AccessChecker {
    public boolean canEdit(Long userId, Object principal) {
        // Custom logic: admin or own profile
        return true; // simplified
    }
}

// Role hierarchy
// @Bean
// RoleHierarchy roleHierarchy() {
//     return RoleHierarchyImpl.withRolePrefix("ROLE_")
//         .role("ADMIN").implies("MANAGER")
//         .role("MANAGER").implies("USER")
//         .build();
// }

Sponsored

Auth0

Use Cases

  • Fine-grained API endpoint authorization
  • Role hierarchy and permission management
  • Custom access control expressions

Tags

Related Snippets

Similar patterns you can reuse in the same workflow.