7

I'm stuck in this issue for a long time. I want to use @Secure to add Access Control to my controller ArticleController.java like this:

@RequestMapping(headers = "Accept=application/json")
@ResponseBody
@Secured("ROLE_ADMIN")
public ResponseEntity<String> listJson() {
    HttpHeaders headers = new HttpHeaders();
    headers.add("Content-Type", "application/json; charset=utf-8");
    List<Article> result = Article.findAllArticles();
    return new ResponseEntity<String>(Article.toJsonArray(result), headers, HttpStatus.OK);
}

listJson return a Json object for Articles but only Admin can read them. OK now I configure the Spring-Security to make this work.

I use security setup function of Spring-ROO, the following configures generated:

In web.xml:

     <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath*:META-INF/spring/applicationContext*.xml</param-value>
     </context-param>
....
    <servlet>
        <servlet-name>BabyPortal</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>WEB-INF/spring/webmvc-config.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

In spring/webmvc-config.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:security="http://www.springframework.org/schema/security" 
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd                 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd                 http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd      http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd   http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">

    <tx:annotation-driven/>
    <!-- The controllers are autodetected POJOs labeled with the @Controller 
        annotation. -->
    <context:component-scan base-package="com.tongxinyuan.babyportal"
        use-default-filters="false">
        <context:include-filter expression="org.springframework.stereotype.Controller"
            type="annotation" />
    </context:component-scan>

    <!-- Turns on support for mapping requests to Spring MVC @Controller methods 
        Also registers default Formatters and Validators for use across all @Controllers -->
    <mvc:annotation-driven conversion-service="applicationConversionService" />


    <!-- Handles HTTP GET requests for /resources/** by efficiently serving 
        up static resources -->
    <mvc:resources location="/, classpath:/META-INF/web-resources/"
        mapping="/resources/**" />

    <!-- Allows for mapping the DispatcherServlet to "/" by forwarding static 
        resource requests to the container's default Servlet -->
    <mvc:default-servlet-handler />

    <!-- Register "global" interceptor beans to apply to all registered HandlerMappings -->
    <mvc:interceptors>
        <bean class="org.springframework.web.servlet.theme.ThemeChangeInterceptor" />
        <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"
            p:paramName="lang" />
    </mvc:interceptors>

    <!-- Selects a static view for rendering without the need for an explicit 
        controller -->
    <mvc:view-controller path="/login" />
    <mvc:view-controller path="/" view-name="index" />
    <mvc:view-controller path="/uncaughtException" />
    <mvc:view-controller path="/resourceNotFound" />
    <mvc:view-controller path="/dataAccessFailure" />

    <!-- Resolves localized messages*.properties and application.properties 
        files in the application to allow for internationalization. The messages*.properties 
        files translate Roo generated messages which are part of the admin interface, 
        the application.properties resource bundle localizes all application specific 
        messages such as entity names and menu items. -->
    <bean
        class="org.springframework.context.support.ReloadableResourceBundleMessageSource"
        id="messageSource" p:basenames="WEB-INF/i18n/messages,WEB-INF/i18n/application"
        p:fallbackToSystemLocale="false" />

    <!-- Store preferred language configuration in a cookie -->
    <bean class="org.springframework.web.servlet.i18n.CookieLocaleResolver"
        id="localeResolver" p:cookieName="locale" />

    <!-- Resolves localized <theme_name>.properties files in the classpath to 
        allow for theme support -->
    <bean
        class="org.springframework.ui.context.support.ResourceBundleThemeSource"
        id="themeSource" />

    <!-- Store preferred theme configuration in a cookie -->
    <bean class="org.springframework.web.servlet.theme.CookieThemeResolver"
        id="themeResolver" p:cookieName="theme" p:defaultThemeName="standard" />

    <!-- This bean resolves specific types of exceptions to corresponding logical 
        - view names for error views. The default behaviour of DispatcherServlet 
        - is to propagate all exceptions to the servlet container: this will happen 
        - here with all other types of exceptions. -->
    <bean
        class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"
        p:defaultErrorView="uncaughtException">
        <property name="exceptionMappings">
            <props>
                <prop key=".DataAccessException">dataAccessFailure</prop>
                <prop key=".NoSuchRequestHandlingMethodException">resourceNotFound</prop>
                <prop key=".TypeMismatchException">resourceNotFound</prop>
                <prop key=".MissingServletRequestParameterException">resourceNotFound</prop>
            </props>
        </property>
    </bean>

    <!-- Enable this for integration of file upload functionality -->
    <bean
        class="org.springframework.web.multipart.commons.CommonsMultipartResolver"
        id="multipartResolver" />
    <bean
        class="com.tongxinyuan.babyportal.controller.ApplicationConversionServiceFactoryBean"
        id="applicationConversionService" />
    <bean class="org.springframework.web.servlet.view.UrlBasedViewResolver"
        id="tilesViewResolver">
        <property name="viewClass"
            value="org.springframework.web.servlet.view.tiles2.TilesView" />
    </bean>
    <bean class="org.springframework.web.servlet.view.tiles2.TilesConfigurer"
        id="tilesConfigurer">
        <property name="definitions">
            <list>
                <value>/WEB-INF/layouts/layouts.xml</value>
                <!-- Scan views directory for Tiles configurations -->
                <value>/WEB-INF/views/**/views.xml</value>
            </list>
        </property>
    </bean>

    <security:global-method-security mode="aspectj" secured-annotations="enabled" pre-post-annotations="enabled"/>

</beans>

In /spring/applicationContext-security.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security" 
    xmlns:beans="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd">
    <!-- HTTP security configurations -->
    <http auto-config="true" use-expressions="true">
        <form-login login-processing-url="/resources/j_spring_security_check" login-page="/login" authentication-failure-url="/login?login_error=t" />
        <logout logout-url="/resources/j_spring_security_logout" />
        <!-- Configure these elements to secure URIs in your application -->
        <intercept-url pattern="/choices/**" access="hasRole('ROLE_ADMIN')" />
        <intercept-url pattern="/member/**" access="isAuthenticated()" />
        <intercept-url pattern="/resources/**" access="permitAll" />
        <intercept-url pattern="/*.html" access="hasRole('ROLE_ADMIN')" />
    </http>
    <!-- Configure Authentication mechanism -->
    <authentication-manager alias="authenticationManager">
        <authentication-provider>
            <user-service>
                <user name="admin" password="admin" authorities="ROLE_ADMIN" />
                <user name="user" password="user" authorities="ROLE_USER" />
            </user-service>
        </authentication-provider>
    </authentication-manager>
</beans:beans>

Firstly I tried adding the <global-method-security mode="aspectj" secured-annotations="enabled" pre-post-annotations="enabled"/> to /spring/applicationContext-security.xml but didn't work. Then maybe the the controller is not in the same context of security context, so I add the to /spring/webmvc-config.xml which started with DispatcherServlet, didn't work.

I also added to another default applicationContext.xml, it didn't work either. I don't know how to configure the <global-method-security> that can make the method security work. It seems I only use one context, did I miss something? Hope the information is enough to make this issue clear.

PS: The generated URL method works very well: <intercept-url pattern="/*.html" access="hasRole('ROLE_ADMIN')" />.

Added: According to @LukeTaylor 's comments: I added the <global-method-security> to webmvc-config.xml and removed the mode="aspectj", it works, and I did some experiments, still have some questions:

1) It works but only for ArticleController.java, the @Secure tag in ArticleController_Roo_Controller.aj still don't work, is that something related to "waving"? 2) Can you explain to me why mode=aspectj make it mess here?

JerryCai
  • 1,663
  • 4
  • 21
  • 36
  • possible duplicate of [@Secured annotations not working in AspectJ Mode with Autoproxy](http://stackoverflow.com/questions/11400503/secured-annotations-not-working-in-aspectj-mode-with-autoproxy) – axtavt Jul 10 '12 at 14:02
  • Why don't you want to use ``? That is the standard way of doing this. – sourcedelica Jul 10 '12 at 14:05
  • @sourcedelica you are right, the reason why I use roo is for its convenience, I cannot spend more time on this. But other tag like `@Async` cannot work either, so I'm thinking of some configure error that might someone here knows. – JerryCai Jul 10 '12 at 14:21
  • As @axtavt says, it looks like you are incorrectly using `mode="aspectj"`. – Shaun the Sheep Jul 11 '12 at 21:00
  • @LukeTaylor I tried to removed the mode, it still didn't work. – JerryCai Jul 12 '12 at 01:18
  • @JerryCai Did you put it in your `webmvc-config.xml` file? – Shaun the Sheep Jul 12 '12 at 13:58
  • 2
    @LukeTaylor refer to your hint, I added the `` to `webmvc-config.xml` and removed the `mode="aspectj"`, it works, and I did some experiments, please check my main question, thank you. – JerryCai Jul 13 '12 at 02:19
  • @LukeTaylor please remove the comment and reply as Answer that I can rank you. – JerryCai Jul 13 '12 at 02:44
  • @JerryCai it would probably make more sense to request deletion of the question, to be honest. It is really a duplicate of the one linked to by axtavt, as well as the common confusion which is cause by Spring's child/parent application context relationship and the visibility of beans between them (also covered on SO and in the Spring Security FAQ). I've added another answer to the other question to clarify some things, so you can vote that up if you wish :-). – Shaun the Sheep Jul 13 '12 at 17:00
  • Thanks everyone it helped me a lot. I am providing a precise answer on basis of your conversations so that other users like me can easily identify the answer without going through the comments. – Japan Trivedi Nov 06 '12 at 10:36

1 Answers1

13

As suggested by @Luke Taylor in the comments the tag <sec:global-method-security/> needs to be defined in the dispatcher-servlet.xml(webmvc-config.xml in this case) file. And there is no need to have attribute mode="aspectj".

Thanks.

Japan Trivedi
  • 4,445
  • 2
  • 23
  • 44
  • 3
    Thank you SOOOOOO Much! I've been banging my head against this particular brick wall for hours now. Why Spring? Why do you need to put security related config in your dispatcher-serlvet config and not in your security config??? I'm sure there must be a good reason.... – pmckeown Oct 17 '13 at 08:07
  • https://docs.spring.io/spring-security/site/faq/faq.html#faq-method-security-in-web-context – Arto Bendiken Jun 29 '20 at 16:22