Method Level Security
- General
Method Level Security
In this article, we will create a simple spring boot application to demonstrate spring method-level security.
What is method-level security?
It can be considered an abstract layer of security that helps us write secure methods. It provides us with some handy annotations that can reduce our work such as @Secured, @RolesAllowed, etc.
Project Structure
We can start creating a spring through spring-initializer or from any IDE of your choice. And add the dependency for spring web and security.
There will be mainly three packages: config, controller, and service
For this blog we are not going to use a database but will be using the in-memory database provided by the spring, so no need for model or repository packages.
The project structure should look similar to :
Don’t worry about the files, we will be creating them one by one.
Enabling Method Security
To use the Spring method security, we need to add the spring-boot-starter-security dependency, which I have already mentioned above:
1 2 3 4 |
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> |
Next, we need to enable global Method Security, for this create a config package, and then create a class namely MethodSecurityConfig :
1 2 3 4 5 6 7 8 |
@Configuration @EnableGlobalMethodSecurity( prePostEnabled = true, securedEnabled = true, jsr250Enabled = true) public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration { } |
- The prePostEnabled property enables Spring Security pre/post annotations.
- The securedEnabled property determines if the @Secured annotation should be enabled.
- The jsr250Enabled property allows us to use the @RoleAllowed annotation.
Let’s move on to fun stuff.
Applying Method Security
Hold up, We first need to configure our users and make some dummy APIs to test, so let’s create them first.
Create a package controller and create a class HomeController, the name can be of your choice, inside this class we will be creating two controllers, one will be secure, and the other will be open.
1 2 3 4 5 6 7 8 9 |
@GetMapping("/home") public String home() { return "Home page"; } @GetMapping("/dashboard") public String dashboard() { return "Dashboard page"; } |
And don’t forget to write @RestController on the class.
Let’s configure which controller will be secured and create some dummy users with different roles.
Create a class MySecurityConfig inside the config package, annotate it with @Configuration, and it should extend WebSecurityConfigurerAdapter.
Let’s override some methods from the adapter and configure them.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
@Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication().withUser("bharat").password("123").roles("ADMIN") .and().withUser("test").password("123").roles("USER") .and().passwordEncoder(NoOpPasswordEncoder.getInstance()); } @Override protected void configure(HttpSecurity http) throws Exception { http .httpBasic() .and() .authorizeRequests() .antMatchers("/home").permitAll() .and() .authorizeRequests() .antMatchers("/dashboard").authenticated() .anyRequest().authenticated() .and() .formLogin() .permitAll(); } |
In the above picture, we have created two users and defined the dashboard path as secured.
Now, finally, we can come back to implement method-level security.
Let’s define a service layer that contains a dummy that should be only accessible by users with role admin, create a package service and then create a class UserService and annotate it with @Service and create a dummy method in it, which will be used from the controller layer in the dashboard API by auto wiring the user Service class.
1 2 3 4 |
@Secured("ROLE_ADMIN") public String getUsername() { return "hi"; } |
we have annotated the method with @Secured, this annotation allows us to define which user’s role can access the method.
Let’s test them :
Testing
Let’s Open postman, and try to hit the endpoint: http://localhost:8080/dashboard with Authorization of username: bharat and password: 123, we will be allowed to access the method, but if we try to access the same endpoint with credentials of username: test and password:123, we will be prompted with 403 forbidden error, because the test user has the role of USER.
This blog just introduced a single annotation @Secured, there are various other annotations such as @RolesAllowed, @PreAuthorize, @PostAuthorize, @PreFilter,@PostFilter, etc.
Here are some references where you can look up other annotations :
Thanks, I really hoped you enjoy reading the blog.
Related content
Auriga: Leveling Up for Enterprise Growth!
Auriga’s journey began in 2010 crafting products for India’s