tutorial - spring-security-config
Preautorizar no funciona en el controlador (4)
Un problema común con el uso de anotaciones PrePost en los controladores es que la seguridad del método Spring se basa en Spring AOP, que se implementa de forma predeterminada con los proxies JDK.
Eso significa que funciona bien en la capa de servicio que se inyecta en la capa de controlador como interfaces, pero se ignora en la capa de controlador porque el controlador generalmente no implementa interfaces.
Lo siguiente es solo mi opinión:
- modo preferido: mover la anotación previa a la publicación en la capa de servicio
- si no puede (o no quiere), intente que su controlador implemente una interfaz que contenga todos los métodos anotados
- como última forma, use proxy-target-class = true
Estoy tratando de definir reglas de acceso a nivel de método, pero no funciona de ninguna manera.
Configuración de seguridad
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().
withUser("user").password("user").roles("USER").and().
withUser("admin").password("admin").roles("ADMIN");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/v2/**").authenticated()
.and()
.httpBasic()
.realmName("Secure api")
.and()
.csrf()
.disable();
}
}
ExampleController
@EnableAutoConfiguration
@RestController
@RequestMapping({"/v2/"})
public class ExampleController {
@PreAuthorize("hasAuthority(''ROLE_ADMIN'')")
@RequestMapping(value = "/home", method = RequestMethod.GET)
String home() {
return "Hello World";
}
}
Cada vez que intento acceder a / v2 / home usando user:user
se ejecuta correctamente, ¿no debería darme un error de acceso denegado debido a que ''user'' no tiene ROLE_ADMIN
?
De hecho, estoy pensando en eliminar las reglas de acceso a nivel de método y atenerme a las reglas de http () ant, pero tengo que saber por qué no me funciona.
Tuve un problema similar y el siguiente lo resolvió:
1) Tuve que hacer público mi método (es decir, hacer que tu método home () sea público)
2) Tengo que usar hasRole en lugar de hasAuthority
Para hacer que funcione en la capa de controlador. Tuve que poner @EnableAspectJAutoProxy en mi clase de configuración. Ejemplo:
@Configuration
@EnableWebMvc
@EnableAspectJAutoProxy
@ComponentScan(basePackages = { "com.abc.fraud.ts.userservices.web.controller" })
public class WebConfig extends WebMvcConfigurerAdapter{
}
Hay dos formas diferentes de usar esto, una es prefijar y otra no. Y quizás cambie @PreAuthorize("hasAuthority(''ROLE_ADMIN'')")
a @PreAuthorize("hasAuthority(''ADMIN'')")
estará bien.
el siguiente es el código fuente de @PreAuthorize
.
private String defaultRolePrefix = "ROLE_";
public final boolean hasAuthority(String authority) {
return hasAnyAuthority(authority);
}
public final boolean hasAnyAuthority(String... authorities) {
return hasAnyAuthorityName(null, authorities);
}
public final boolean hasRole(String role) {
return hasAnyRole(role);
}
public final boolean hasAnyRole(String... roles) {
return hasAnyAuthorityName(defaultRolePrefix, roles);
}