Utilizo Spring Security y un token JWT. No es posible aplicar el rol de administrador en sus permisos.
Aquí está la clase de configuración donde distribuyo el acceso según los roles:
@Configuration
@EnableWebSecurity
@AllArgsConstructor
//@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurity extends WebSecurityConfigurerAdapter {
private final UserDetailServiceImpl userDetailsService;
private final BCryptPasswordEncoder bCryptPasswordEncoder;
private static final String[] PUBLIC_URLS = {
"/v2/api-docs",
"/swagger-resources/**",
"/swagger-ui/**",
"/webjars/**"
};
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable().authorizeRequests()
.antMatchers(HttpMethod.POST, SIGN_UP_URL).permitAll()
.antMatchers(PUBLIC_URLS).permitAll()
.antMatchers ("/user/**").hasAnyRole ("USER", "ADMIN")
.antMatchers("/user/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.addFilter(new JWTAuthenticationFilter(authenticationManager()))
.addFilter(new JWTAuthorizationFilter(authenticationManager()))
/* this disables session creation on Spring Security */
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder);
}
@Bean
CorsConfigurationSource corsConfigurationSource() {
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", new CorsConfiguration().applyPermitDefaultValues());
return source;
}
}
Esta es la clase del controlador donde quiero usar el rol de administrador:
@AllArgsConstructor
@Validated
@RestController
@RequestMapping("/user")
@Api(tags = "Users")
public class UserController {
private final UserService userService;
@DeleteMapping("/admin/{id}")
@PreAuthorize("hasRole('ADMIN')")
public ResponseEntity<void> delete(@PathVariable @Min(1) int id) {
userService.delete(id);
return ResponseEntity.ok().build();
}
}
Si elimina el siguiente código:
.antMatchers ("/user/").hasAnyRole ("USER", "ADMIN")
.antMatchers("/user/admin/").hasRole("ADMIN")
Luego, el usuario también lo eliminará. Pero si deja este emparejamiento de roles y realiza una solicitud desde el administrador, se produce un error al eliminar el usuario.
{
"timestamp": "2021-12-01T21:30:05.647+00:00",
"status": 403,
"error": "Forbidden",
"message": "",
"path": "/user/admin/2"
}
Si deja esta anotación @EnableGlobalMethodSecurity(prePostEnabled = true)
, entonces nuevamente se produce el mismo error y no se puede eliminar nada.
¿Hay alguna sugerencia para resolver este problema?
davy.ai
Si desea restringir el acceso al endpoint de eliminación solamente al rol ADMIN, puede modificar la configuración de WebSecurity eliminando la siguiente línea:
Esta línea permite que tanto los roles USER como ADMIN tengan acceso a cualquier endpoint que comience con “/user/”. Al eliminarla, solo los usuarios con el rol ADMIN podrán acceder al endpoint “/user/admin/{id}”.
Sin embargo, también debe asegurarse de que el usuario administrador esté autenticado y tenga asignado el rol ADMIN. Para hacerlo, puede modificar JWTAuthenticationFilter para agregar el rol en el token JWT cuando el usuario inicie sesión:
Luego, puede modificar JWTAuthorizationFilter para verificar si el usuario tiene el rol ADMIN en el token JWT:
Con estas modificaciones, solo los usuarios autenticados con el rol ADMIN podrán acceder al endpoint de eliminación.</string,></string,></string,>