Can Spring use @PreAuthorize security in Spring controller methods?

Can Spring use @PreAuthorize security in Spring controller methods?

+61
java spring-mvc spring-security controller
Jun 21 '10 at 18:53
source share
6 answers

Yes, it works great.

You need <security:global-method-security pre-post-annotations="enabled" /> in ...-servlet.xml . It also requires a CGLIB proxy , so either your controllers should not have interfaces, or use proxy-target-class = true .

+63
Jun 21 '10 at 19:07
source share

See Spring Security FAQ (emphasis mine).

In a Spring web application, the application context that contains the Spring MVC beans for the dispatcher servlet is often separated from the main application context. It is often defined in a file called myapp-servlet.xml, where "myapp" is the name assigned to SpringDispatcherServlet in web.xml. An application can have multiple DispatcherServlets, each with its own isolated application context. beans in these "child" contexts are not visible to the rest of the expression. The context of the "parent" application is loaded by the ContextLoaderListener, which you define in your web.xml and are visible to all child contexts. This parent context is usually used where you define your security configuration, including the element). As a result, any security restrictions applied to the methods in these beans web pages will not apply, since beans cannot be seen from the DispatcherServlet context. You need to either move the ads to the web context or the beans that you want to capture in the main context of the application.

We generally recommend that you use the security method in the service and not on individual web controllers.

If you apply pointcuts to a service level, you need to set <global-method-security> in the application security context.

+19
Jul 05 2018-12-12T00:
source share

If you are using Spring 3.1, you can do some pretty cool stuff with this. Take a look at https://github.com/mohchi/spring-security-request-mapping . This is an example project that combines @PreAuthorize with Spring MVC RequestMappingHandlerMapping so you can do something like:

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

A request for "/" calls HomePage () authentication if the user is authenticated. Otherwise, it will call homePage ().

+16
Sep 25 '12 at 0:00
source share

For two years since this question was asked, but due to the problems that I encountered today, I would prefer to stop using @Secured , @PreAuthorize , etc. on @Controller s.

For me there was no @Validated in combination with the @Secured controller:

 @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) { // ... } 

The validator simply does not start (Spring MVC 4.1.2, Spring Security 3.2.5) and no checks are performed.

Similar problems are caused by CGLIB proxies used by Spring (in the absence of an interface implemented by a class, Spring creates a CGLIB proxy; if the class implements any interface, then JDK proxies are created - the documentation is well explained here and here ).

As mentioned in the answers that were linked above, it is better to use Spring service-level security annotations that usually implement interfaces (which is why JDK proxies are used), since this does not lead to such problems.

If you want to protect web controllers, it is better to use <http> and <intercept-url /> , which are bound to specific URLs, rather than methods in controllers and work very well. In my case:

 <http use-expressions="true" disable-url-rewriting="true"> ... <intercept-url pattern="/administration/**" access="hasRole('ROLE_ADMIN')" /> </http> 
+8
Dec 26 '14 at 1:29
source share

To extend the answer provided by Andy, you can use:

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

to check a specific role.

+1
Aug 13 '16 at 11:33
source share

There is already an answer on how to make it work by changing the xml configuration, however, if you work with code-based configuration, you can achieve the same by setting the following @Configuration class annotation: @EnableGlobalMethodSecurity(prePostEnabled=true) .

0
03 Sep '17 at 14:35
source share



All Articles