Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can <global-method-security> work on my controller by Spring-Security?

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?

like image 642
JerryCai Avatar asked Jul 10 '12 13:07

JerryCai


1 Answers

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.

like image 84
Japan Trivedi Avatar answered Sep 23 '22 17:09

Japan Trivedi