¿Puede Spring Security usar @PreAuthorize en los métodos de los controladores Spring?

¿Puede Spring Security usar @PreAuthorize en los métodos de los controladores Spring?

Sí, funciona bien.

Necesita in ...-servlet.xml . También requiere proxies CGLIB , por lo tanto, sus controladores no deberían tener interfaces, o debería usar proxy-target-class = true .

Ver las preguntas frecuentes de Spring Security (énfasis mío).

En una aplicación web de Spring, el contexto de la aplicación que contiene los beans de Spring MVC para el servlet del despachador a menudo está separado del contexto de la aplicación principal. A menudo se define en un archivo llamado myapp-servlet.xml, donde “myapp” es el nombre asignado al Spring DispatcherServlet en web.xml. Una aplicación puede tener múltiples DispatcherServlets, cada uno con su propio contexto de aplicación aislado. Los beans en estos contextos “secundarios” no son visibles para el rest de la aplicación. El ContextLoaderListener que usted define en su web.xml carga el contexto de la aplicación “principal” y es visible para todos los contextos secundarios. Este contexto principal generalmente es donde define su configuración de seguridad, incluido el elemento). Como resultado, no se aplicarán las restricciones de seguridad aplicadas a los métodos en estos beans web, ya que los beans no se pueden ver desde el contexto DispatcherServlet. Debe mover la statement al contexto web o mover los beans que desea asegurar al contexto principal de la aplicación.

En general, recomendaríamos aplicar la seguridad del método en la capa de servicio en lugar de en los controladores web individuales.

Si aplica puntos de corte a la capa de servicio, solo necesita establecer en el contexto de seguridad de su aplicación.

Si está utilizando Spring 3.1, puede hacer algunas cosas muy interesantes con esto. Eche un vistazo a https://github.com/mohchi/spring-security-request-mapping . Es un proyecto de muestra que integra @PreAuthorize con RequestMappingHandlerMapping de Spring MVC para que pueda hacer algo como:

 @RequestMapping("/") @PreAuthorize("isAuthenticated()") public String authenticatedHomePage() { return "authenticatedHomePage"; } @RequestMapping("/") public String homePage() { return "homePage"; } 

Una solicitud de “/” llamará a authenticatedHomePage () si el usuario está autenticado. De lo contrario, llamará homePage ().

Han pasado más de dos años desde que se hizo esta pregunta pero, debido a los problemas que tuve hoy, preferiría desalentar el uso de @Secured , @PreAuthorize , etc. en @Controller s.

Lo que no funcionó para mí fue @Validated combinado con el controlador @Secured :

 @Controller @Secured("ROLE_ADMIN") public class AdministrationController { // @InitBinder here... @RequestMapping(value = "/administration/add-product", method = RequestMethod.POST) public String addProductPost(@ModelAttribute("product") @Validated ProductDto product, BindingResult bindingResult) { // ... } 

El validador simplemente no se activa (Spring MVC 4.1.2, Spring Security 3.2.5) y no se realizan comprobaciones.

Problemas similares son causados ​​por los proxys CGLIB utilizados por Spring (cuando no hay una interfaz implementada por una clase, Spring crea el proxy CGLIB, si la clase implementa cualquier interfaz se genera JDK Proxy – documentación , bien explicada aquí y aquí ).

Como mencioné en las respuestas que he vinculado anteriormente, no es mejor usar las anotaciones de Spring Security en la capa de servicio que generalmente implementa interfaces (por lo que se utilizan los Proxy JDK) ya que esto no genera tales problemas.

Si desea proteger los controladores web, la mejor idea es usar y que están vinculados a direcciones URL específicas en lugar de a métodos en controladores y funcionan bastante bien. En mi caso:

  ...   

Ya hay una respuesta sobre cómo hacer que funcione cambiando la configuración xml; sin embargo, si está trabajando con una configuración basada en código, puede lograr lo mismo colocando la siguiente anotación sobre su clase @Configuration :

 @EnableGlobalMethodSecurity(prePostEnabled=true) 

Para extender la respuesta proporcionada por Andy, puede usar:

 @PreAuthorize("hasRole('foo')") 

para verificar el rol específico.

Primero necesita agregar esta anotación en su WebSecurityConfig para habilitar las anotaciones @Pre y @Post.

  @EnableGlobalMethodSecurity(prePostEnabled = true) 

También puede verificar roles / autoridades de la siguiente manera

  @PreAuthorize("hasAuthority('ROLE_ADMIN')") 

equivalente a

  @PreAuthorize("hasRole('ROLE_ADMIN')") 

También puede verificar múltiples roles / autoridades de la siguiente manera

  @PreAuthorize("hasAuthority('ROLE_ADMIN') or hasAuthority('ROLE_USER') or ...")