Swiftorial Logo
Home
Swift Lessons
Tutorials
Learn More
Career
Resources

Method Security

Method security in Spring allows you to secure individual methods in your application by specifying security constraints at the method level. This guide covers the key concepts and steps for enabling and using method security in Spring applications, including setting up dependencies, enabling method security, and using key annotations like @PreAuthorize, @PostAuthorize, @Secured, and @RolesAllowed.

Key Concepts of Method Security

  • @PreAuthorize: Specifies a method should be accessible only if the specified expression evaluates to true before the method is invoked.
  • @PostAuthorize: Specifies a method should be accessible only if the specified expression evaluates to true after the method is invoked.
  • @Secured: Specifies one or more roles that are allowed to invoke a method.
  • @RolesAllowed: Similar to @Secured but uses standard JSR-250 annotations.
  • @EnableGlobalMethodSecurity: Enables method-level security.

Adding Dependencies

Include the Spring Security dependency in your pom.xml file:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

Enabling Method Security

Enable method security by adding the @EnableGlobalMethodSecurity annotation in your configuration class:

Example: SecurityConfiguration.java

// SecurityConfiguration.java
package com.example.myapp.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true)
public class SecurityConfiguration {
    // Security configuration code
}

Using @PreAuthorize

The @PreAuthorize annotation is used to specify an authorization expression that will be evaluated before a method is invoked:

Example: MyService.java

// MyService.java
package com.example.myapp.service;

import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;

@Service
public class MyService {

    @PreAuthorize("hasRole('ADMIN')")
    public void adminMethod() {
        // Admin only logic
    }

    @PreAuthorize("hasRole('USER')")
    public void userMethod() {
        // User only logic
    }
}

Using @PostAuthorize

The @PostAuthorize annotation is used to specify an authorization expression that will be evaluated after a method is invoked:

Example: MyService.java

// MyService.java
package com.example.myapp.service;

import org.springframework.security.access.prepost.PostAuthorize;
import org.springframework.stereotype.Service;

@Service
public class MyService {

    @PostAuthorize("returnObject.owner == authentication.name")
    public MyObject getObject() {
        // Method logic
        return new MyObject();
    }
}

Using @Secured

The @Secured annotation is used to specify one or more roles that are allowed to invoke a method:

Example: MyService.java

// MyService.java
package com.example.myapp.service;

import org.springframework.security.access.annotation.Secured;
import org.springframework.stereotype.Service;

@Service
public class MyService {

    @Secured("ROLE_ADMIN")
    public void adminMethod() {
        // Admin only logic
    }

    @Secured({"ROLE_USER", "ROLE_ADMIN"})
    public void userOrAdminMethod() {
        // User or Admin logic
    }
}

Using @RolesAllowed

The @RolesAllowed annotation is similar to @Secured but uses standard JSR-250 annotations:

Example: MyService.java

// MyService.java
package com.example.myapp.service;

import javax.annotation.security.RolesAllowed;
import org.springframework.stereotype.Service;

@Service
public class MyService {

    @RolesAllowed("ROLE_ADMIN")
    public void adminMethod() {
        // Admin only logic
    }

    @RolesAllowed({"ROLE_USER", "ROLE_ADMIN"})
    public void userOrAdminMethod() {
        // User or Admin logic
    }
}

Example: Full Configuration and Service

Here is a full example combining security configuration and service method annotations:

Example: SecurityConfiguration.java

// SecurityConfiguration.java
package com.example.myapp.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

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

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
            .withUser("user")
            .password(passwordEncoder().encode("password"))
            .roles("USER")
            .and()
            .withUser("admin")
            .password(passwordEncoder().encode("admin"))
            .roles("ADMIN");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
            .authorizeRequests()
            .antMatchers("/public/**").permitAll()
            .anyRequest().authenticated()
            .and()
            .formLogin()
            .loginPage("/login")
            .permitAll()
            .and()
            .logout()
            .permitAll();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

Example: MyService.java

// MyService.java
package com.example.myapp.service;

import org.springframework.security.access.annotation.Secured;
import org.springframework.security.access.prepost.PostAuthorize;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;

@Service
public class MyService {

    @PreAuthorize("hasRole('ADMIN')")
    public void adminMethod() {
        // Admin only logic
    }

    @PreAuthorize("hasRole('USER')")
    public void userMethod() {
        // User only logic
    }

    @PostAuthorize("returnObject.owner == authentication.name")
    public MyObject getObject() {
        // Method logic
        return new MyObject();
    }

    @Secured("ROLE_ADMIN")
    public void securedAdminMethod() {
        // Admin only logic
    }

    @Secured({"ROLE_USER", "ROLE_ADMIN"})
    public void securedUserOrAdminMethod() {
        // User or Admin logic
    }

    @RolesAllowed("ROLE_ADMIN")
    public void rolesAllowedAdminMethod() {
        // Admin only logic
    }

    @RolesAllowed({"ROLE_USER", "ROLE_ADMIN"})
    public void rolesAllowedUserOrAdminMethod() {
        // User or Admin logic
    }
}

Key Points

  • @PreAuthorize: Specifies a method should be accessible only if the specified expression evaluates to true before the method is invoked.
  • @PostAuthorize: Specifies a method should be accessible only if the specified expression evaluates to true after the method is invoked.
  • @Secured: Specifies one or more roles that are allowed to invoke a method.
  • @RolesAllowed: Similar to @Secured but uses standard JSR-250 annotations.
  • @EnableGlobalMethodSecurity: Enables method-level security.
  • Enable method security by adding the @EnableGlobalMethodSecurity annotation in your configuration class.
  • Use @PreAuthorize and @PostAuthorize to secure methods with authorization expressions.
  • Use @Secured and @RolesAllowed to specify roles that can invoke methods.
  • Combine security configuration and service method annotations to secure your Spring Boot application effectively.

Conclusion

Method security in Spring allows you to secure individual methods by specifying security constraints at the method level. By understanding and using key annotations like @PreAuthorize, @PostAuthorize, @Secured, and @RolesAllowed, you can implement fine-grained security controls in your Spring Boot application. Happy coding!