Mastering Spring Security: Fine-Grained Method Permissions with @PreAuthorize

This tutorial demonstrates how to secure Spring Boot REST endpoints using Spring Security, covering URL‑based rules, enabling method‑level security, and applying @PreAuthorize, @RolesAllowed, and @Secured annotations for precise access control.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Mastering Spring Security: Fine-Grained Method Permissions with @PreAuthorize

Spring Security Permission Control Series (6)

Environment: Spring Boot 2.4.12 + Spring Security 5.4.9

Demo Controller

@RestController
@RequestMapping("/business")
public class BussinessController {
    @GetMapping("/{id}")
    public Object get(@PathVariable("id") Integer id) {
        return "receive - " + id ;
    }
}

Security Configuration (URL‑based)

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();
        http.authorizeRequests().antMatchers("/resources/**", "/cache/**", "/process/login").permitAll();
        http.authorizeRequests().antMatchers("/demos/**").hasRole("USERS");
        http.authorizeRequests().antMatchers("/api/**").hasRole("ADMIN");
        // Require authentication for all /business/** requests
        http.authorizeRequests().antMatchers("/business/**").authenticated();
    }
}

After this configuration, accessing http://localhost:8080/business/100 prompts for login; once authenticated, the endpoint is reachable.

Method‑Level Security

Enable annotation‑based security on methods:

@Configuration
@EnableGlobalMethodSecurity(jsr250Enabled = true, prePostEnabled = true, securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
}

Key attributes:

jsr250Enabled : enables support for JSR‑250 annotations such as @RolesAllowed.

prePostEnabled : enables expression‑based annotations like @PreAuthorize and @PostAuthorize.

securedEnabled : enables the @Secured annotation.

Annotation Examples

@GetMapping("/{id}")
@RolesAllowed("ROLE_USERS") // ① can specify multiple roles as a String[]
@Secured("ROLE_USERS1")   // ② can also specify multiple roles
@PreAuthorize("hasRole('USERS')") // ③ supports SpEL expressions
public Object get(@PathVariable("id") Integer id) {
    return "receive - " + id ;
}

Only the @PreAuthorize example is demonstrated here; the other two are straightforward.

Using @PreAuthorize

The annotation evaluates an expression to decide whether the method may be invoked. Common expressions include: hasRole('USERS') – the caller must have the USERS role. hasAnyRole('USERS','ADMIN') – the caller needs any of the listed roles. hasAuthority('bus:news:see') – the caller must possess the specific authority. hasAnyAuthority('bus:news:see','bus:news:write') – any listed authority is sufficient.

These expressions are evaluated by SecurityExpressionRoot:

public abstract class SecurityExpressionRoot implements SecurityExpressionOperations {
    private String defaultRolePrefix = "ROLE_";
    @Override
    public final boolean hasRole(String role) {
        return hasAnyRole(role);
    }
    @Override
    public final boolean hasAnyRole(String... roles) {
        return hasAnyAuthorityName(this.defaultRolePrefix, roles);
    }
    @Override
    public final boolean hasAuthority(String authority) {
        return hasAnyAuthority(authority);
    }
    @Override
    public final boolean hasAnyAuthority(String... authorities) {
        return hasAnyAuthorityName(null, authorities);
    }
    private boolean hasAnyAuthorityName(String prefix, String... roles) {
        Set<String> roleSet = getAuthoritySet();
        for (String role : roles) {
            String defaultedRole = getRoleWithDefaultPrefix(prefix, role);
            if (roleSet.contains(defaultedRole)) {
                return true;
            }
        }
        return false;
    }
}

Both hasRole and hasAuthority ultimately delegate to hasAnyAuthorityName, with hasRole automatically adding the ROLE_ prefix.

Summary

The article covered various ways to control access to business‑level controller endpoints, including URL‑based rules and fine‑grained method‑level annotations such as @PreAuthorize, @RolesAllowed, and @Secured. The next article will explore custom authentication/authorization and advanced @PreAuthorize usage.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

javabackend-developmentspring-securityMethod SecurityPreAuthorize
Spring Full-Stack Practical Cases
Written by

Spring Full-Stack Practical Cases

Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.