Previously once you authenticated with credentials, both "/all" and "{id}" urls were exposed to both users.
One is Admin and other oner is with USER privileges.
Now let's see handle authorization.
Case :
"products/all" - Admin
"products/{id}" = USER
How to do that
1. Add method level annotation for mention the authorization level
@PreAuthorize("hasAuthority('ROLE_ADMIN')")
eg:
@GetMapping("/all")
@PreAuthorize("hasAuthority('ROLE_ADMIN')")
public List<Product> getAllTheProducts() {
return service.getProducts();
}
@GetMapping("/{id}")
@PreAuthorize("hasAuthority('ROLE_USER')")
public Product getProductById(@PathVariable int id) {
return service.getProduct(id);
}
But this is not enough
2. We need to enable Method level security in our "SecurityConfig" class. For that we add annotation "@EnableMethodSecurity"
sample as shown below
@RequiredArgsConstructor
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class SecurityConfig {
3. Now you can try to access after login with credentials
eg: logged with ADMIN {Alex,Pwd1}
Then you can access only /products/all
If you try to access /products/{id}
you will most probably get a message like
--------------------------
Access to localhost was denied
You don't have authorization to view this page.
------------------------
Below are two full code samples
package com.example.springsecurityjavaTechie.config;
import lombok.RequiredArgsConstructor;
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.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
@RequiredArgsConstructor
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class SecurityConfig {
@Bean
UserDetailsService userDetailsService(PasswordEncoder passwordEncoder) {
// authentication
UserDetails admin = User.withUsername("Alex")
.password(passwordEncoder.encode("Pwd1"))
.roles("ADMIN")
.build();
UserDetails user = User.withUsername("John")
.password(passwordEncoder().encode("Pwd2"))
.roles("USER")
.build();
return new InMemoryUserDetailsManager(admin, user);
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
return httpSecurity.csrf().disable()
.authorizeHttpRequests()
.requestMatchers("/products/welcome").permitAll()//just let any one access
.and()
.authorizeHttpRequests().requestMatchers("/products/**")
.authenticated().and().formLogin().and().build();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
package com.example.springsecurityjavaTechie.controller;
import com.example.springsecurityjavaTechie.model.Product;
import com.example.springsecurityjavaTechie.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping("/products")
public class ProductController {
@Autowired
private ProductService service;
@GetMapping("/welcome")
public String welcome() {
return "Welcome this endpoint is not secure";
}
// @PostMapping("/new")
// public String addNewUser(@RequestBody UserInfo userInfo){
// return service.addUser(userInfo);
// }
@GetMapping("/all")
@PreAuthorize("hasAuthority('ROLE_ADMIN')")
public List<Product> getAllTheProducts() {
return service.getProducts();
}
@GetMapping("/{id}")
@PreAuthorize("hasAuthority('ROLE_USER')")
public Product getProductById(@PathVariable int id) {
return service.getProduct(id);
}
}
No comments:
Post a Comment