Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

@Secured does not work in controller, but intercept-url seems to be working fine

It doesn't look like @Secured on methods in my @Controller are being read. When security filtering based on sec:intercept-url is being used, this seems to be working just fine. The following code results in Spring Security giving me this log entry:

DEBUG: org.springframework.security.web.access.intercept.FilterSecurityInterceptor - Public object - authentication not attempted

web.xml

contextConfigLocation /WEB-INF/spring/root-context.xml

<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<!-- Processes application requests -->
<servlet>
    <servlet-name>appServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/spring/appServlet/servlet-context.xml
        </param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

<!-- Filter security -->
<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

servlet-context.xml holds the configuration of the viewResolvers and all the marshalling. This configuration is annotation-driven.

root-context.xml

    <sec:global-method-security secured-annotations="enabled" />

<sec:http auto-config="true">
    <sec:http-basic/>
</sec:http>

<!-- Declare an authentication-manager to use a custom userDetailsService -->
<sec:authentication-manager>
    <sec:authentication-provider
        user-service-ref="userDetailsService">
        <sec:password-encoder ref="passwordEncoder" />
    </sec:authentication-provider>
</sec:authentication-manager>

<bean
    class="org.springframework.security.authentication.encoding.PlaintextPasswordEncoder"
    id="passwordEncoder" />
<sec:user-service id="userDetailsService">
    <sec:user name="john" password="john" authorities="ROLE_USER, ROLE_ADMIN" />
    <sec:user name="jane" password="jane" authorities="ROLE_USER" />
</sec:user-service>

PingController.java

@Controller
public class PingController {

    @Secured("ROLE_ADMIN")
    @RequestMapping(value = "/ping", method = RequestMethod.GET)
    public void ping() {
    }

}

This doesn't seem to have any relation to which authentication method I'm using, so the basic-http-tag can be overlooked.

I have this idea that the @Secured doesn't work because of it being used in another context than the root-context.xml in which the security is being configured. I've tried to move this configuration to the servlet-context.xml, but it doesn't seem to reach the springSecurityFilterChain. Any thoughts on the problem and and my theory?

like image 961
kareblak Avatar asked Jul 11 '11 13:07

kareblak


2 Answers

You are right, <global-method-security> is applied at per-context basis. However, you don't need to move the whole security configuration to servlet-context.xml, just add a <global-method-security> element to it.

like image 137
axtavt Avatar answered Nov 10 '22 08:11

axtavt


See Spring Security FAQ (emphasis mine). If you apply pointcuts to service layer you only need to set <global-method-security> in your app's security context.

In a Spring web application, the application context which holds the Spring MVC beans for the dispatcher servlet is often separate from the main application context. It is often defined in a file called myapp-servlet.xml, where “myapp” is the name assigned to the Spring DispatcherServlet in web.xml. An application can have multiple DispatcherServlets, each with its own isolated application context. The beans in these “child” contexts are not visible to the rest of the application. The “parent” application context is loaded by the ContextLoaderListener you define in your web.xml and is visible to all the child contexts. This parent context is usually where you define your security configuration, including the element). As a result any security constraints applied to methods in these web beans will not be enforced, since the beans cannot be seen from the DispatcherServlet context. You need to either move the declaration to the web context or moved the beans you want secured into the main application context.

Generally we would recommend applying method security at the service layer rather than on individual web controllers.

like image 23
Tomasz Avatar answered Nov 10 '22 08:11

Tomasz