How does <global-method-security> work on my controller using Spring-Security?
I am stuck with this problem for a long time. I want to use @Secure
to add access control to my ArticleController.java
controller as follows:
@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 returns a Json object for Articles
, but only the administrator can read them. Now I'm setting up Spring-Security to make this work.
I use the security setup
function Spring -ROO, the following configurations are created:
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 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>
First I tried adding <global-method-security mode="aspectj" secured-annotations="enabled" pre-post-annotations="enabled"/>
to /spring/applicationContext-security.xml
, but it didn’t work. Then, perhaps, the controller is not in the same context of the security context, so I add to /spring/webmvc-config.xml
, which started with DispatcherServlet, did not work.
I also added applicationContext.xml
to the other default, it didn't work either. I do not know how to configure <global-method-security>
, which can make the method security work. It seems that I use only one context, am I missing something? I hope that there is enough information to make this problem clear.
PS: The generated URL method works very well: <intercept-url pattern="/*.html" access="hasRole('ROLE_ADMIN')" />
.
Added: According to comments of @LukeTaylor: I added <global-method-security>
to webmvc-config.xml
and removed mode="aspectj"
, it works, and I did some experiments, there are still some questions:
1) It works, but only for ArticleController.java, the @Secure tag in ArticleController_Roo_Controller.aj still doesn’t work, is it something that is related to “swinging”? 2) Can you explain to me why mode=aspectj
do it here?