Spring Security + MVC - @Secured - Already declared global-method-security in *servlet.xml

Hope someone could help me.

I am trying to configure Spring Security 3.1 with Spring MVC 3.0.8 but the annotated controllers does not get the access restricted by Spring.

web.xml

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
        /WEB-INF/Spring/applicationContext-security.xml
        /WEB-INF/Spring/applicationContext.xml
    </param-value>
</context-param>

<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>

<!-- Sitemash -->
<filter>
    <filter-name>sitemesh</filter-name>
    <filter-class>com.opensymphony.module.sitemesh.filter.PageFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>sitemesh</filter-name>
    <url-pattern>/*</url-pattern>
    <!-- <servlet-name>referencia</servlet-name> -->
</filter-mapping>

<!-- Spring Listeners -->

<listener>
    <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
</listener>
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
    <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>

<error-page>
    <error-code>500</error-code>
    <location>/erroInterno.jsp</location>
</error-page>

<servlet>
    <servlet-name>stc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>stc</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

<welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
</welcome-file-list>

<session-config>
    <session-timeout>30</session-timeout>
</session-config>

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p" 
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:oxm="http://www.springframework.org/schema/oxm"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:task="http://www.springframework.org/schema/task"
    xmlns:security="http://www.springframework.org/schema/security" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
            http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm-3.0.xsd
            http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.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.xsd
            http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd">

<!-- import the dataSource definition -->
<import resource="applicationContext-dataSource.xml"/>

<!-- Pacote base que sera scaneada por componentes annotados que serao auto-registrados como Spring beans.-->
<context:component-scan base-package="br.com.cielo.portalcontestacao" />

<!-- Ativa a detecao de annotations nas classes -->
<context:annotation-config />

<!-- Configures the annotation-driven Spring MVC Controller programming model.
Note that, with Spring 3.0, this tag works in Servlet MVC only! -->
<mvc:annotation-driven  />

<!-- Recursos utilizados nos imports das páginas -->
<mvc:resources mapping="/resources/**" location="/static/" cache-period="31556926"/>

<!-- Template para uso nos DAOs -->
<bean id="namedParameterJdbcTemplate" class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
    <constructor-arg ref="dataSource" />
</bean>

<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    <constructor-arg ref="dataSource" />
</bean>

<task:executor id="taskExecutor" pool-size="0-3" queue-capacity="0" rejection-policy="CALLER_RUNS" keep-alive="300"/>
<task:annotation-driven executor="taskExecutor" />

<bean id="lobHandler" class="org.springframework.jdbc.support.lob.OracleLobHandler">
</bean>

<!-- Configuração de Locale -->
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver">
    <property name="defaultLocale" value="pt_BR" />
</bean>

<!-- Annotação para controle de transações na aplicação -->
<tx:annotation-driven transaction-manager="transactionManager"/>

<!-- Indica qual o transaction manager a ser utilizado -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/>
    <property name="nestedTransactionAllowed" value="true"/>
</bean>

<!-- Mensagens do sistema --> 
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
   <property name="basename" value="mensagens" />
</bean>

<bean name="stcProperties" class="br.com.cielo.portalcontestacao.service.utils.STCProperties"/>

<bean name="serviceInvoker" class="br.com.cielo.portalcontestacao.service.ServiceInvokerImpl"/>
</beans>

applicationContext-security.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns:beans="http://www.springframework.org/schema/beans"
xmlns="http://www.springframework.org/schema/security" 
xmlns:context="http://www.springframework.org/schema/context"
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.0.xsd 
    http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">

<http pattern="/static/**" security="none"/>
<http pattern="/" security="none"/>

<http auto-config='true' disable-url-rewriting="true" use-expressions="true">
    <intercept-url pattern="/pages/login" access="anonymous or fullyAuthenticated" />
    <form-login login-page="/pages/login"  />

    <session-management session-fixation-protection="newSession">
        <concurrency-control max-sessions="1" />
    </session-management>
</http>

<beans:bean id='userDetailsService'
    class="br.com.cielo.portalcontestacao.security.UserDetailsServiceImpl">
    <beans:property name="jdbcTemplate" ref="jdbcTemplate"/>
    <beans:property name="namedParameterJdbcTemplate" ref="namedParameterJdbcTemplate"/>
</beans:bean>

<beans:bean id='stcAuthenticationProvider'
    class="br.com.cielo.portalcontestacao.security.AuthenticationProviderServiceImpl">
    <beans:property name="serviceInvoker" ref="serviceInvoker"/>
    <beans:property name="userDetailsService" ref="userDetailsService"/>
</beans:bean>

<authentication-manager erase-credentials="true">
    <authentication-provider ref='stcAuthenticationProvider' />
</authentication-manager>
</beans:beans>

stc-servlet.xml

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

<!--context:annotation-config/-->
<security:global-method-security secured-annotations="enabled"/>

<mvc:view-controller path="/pages/login" view-name="login"/>
<mvc:view-controller path="/pages/home" view-name="index"/>
<mvc:view-controller path="/pages/acessonegado" view-name="acessoNegado"/>

<!-- Declara as Exceptions a serem tratadas pelo framework -->
<!--bean class="br.com.cielo.portalcontestacao.service.exceptions.GenericException">
    <property name="exceptionMappings">
        <props>
            <prop key="java.lang.Exception">dataAccessFailure</prop>
            <prop key="org.springframework.web.servlet.PageNotFound">pageNotFound</prop>
            <prop key="org.springframework.dao.DataAccessException">dataAccessFailure</prop>
            <prop key="org.springframework.transaction.TransactionException">dataAccessFailure</prop>
        </props>
    </property>
</bean-->

<!-- Declaracao dos Views Resolvers utilizados na aplicacao -->
<bean class="org.springframework.web.servlet.view.XmlViewResolver">
    <property name="order" value="0" />
</bean>

<bean class="org.springframework.web.servlet.view.ResourceBundleViewResolver">
   <property name="basename" value="views"/>
   <property name="order" value="1" />
</bean>

<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
    <property name="prefix" value="/WEB-INF/jsp/"/>
    <property name="suffix" value=".jsp"/>
    <property name="order" value="0" />
</bean>

<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
    <property name="basename" value="mensagens"/>
</bean>

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
     <!-- one of the properties available; the maximum file size in bytes -->
     <property name="maxUploadSize" value="10000000" />
 </bean>
</beans>

Here is some class that I want the access restricted by Spring Security: imports ommited

ImportacaoArquivo.java

@Secured("ROLE_SCHEDULE")
@Controller
public class ImportacaoArquivo {

    @Secured("ROLE_SCHEDULE")
    @RequestMapping(value = "/pages/schedules", method = RequestMethod.GET)
    public final ModelAndView exibirPageLinks(final HttpServletRequest request) {
        return new ModelAndView("arquivo");
    }
}

Upvotes: 0

Views: 2835

Answers (3)

killmarils
killmarils

Reputation: 21

delete 'final' keyword from the method in your ImportacaoArquivo.java file:

@Secured("ROLE_SCHEDULE")
@RequestMapping(value = "/pages/schedules", method = RequestMethod.GET)
public ModelAndView exibirPageLinks(final HttpServletRequest request) {
    return new ModelAndView("arquivo");
}

Upvotes: 0

Luciano
Luciano

Reputation: 8582

So, this is the information I've gathered from reading different sources:

  • Your <security:global-method-security /> has to be declared in stc-servlet.xml
  • <context:component-scan /> for your your controllers has to be declared in stc-servlet.xml. The scanning for the rest of your beans may remain in applicationContext.xml. This would work best if your controllers are contained inside one package and nothing else is there (for instance br.com.cielo.portalcontestacao.controllers).
  • Also on stc-servlet.xml you need to define <aop:config proxy-target-class="true" />. This instructs Spring to use CGLib to advice methods and classes, and you need that because your controllers do not implement any interface.

Alternative solutions:

  • Use regular intercept-url to define which endpoints have to be secure.
  • Use @Secured annotation on your services instead of using it on the controllers.

Upvotes: 0

axtavt
axtavt

Reputation: 242706

<security:global-method-security /> should be declared in the same context where beans you want to secure are declared.

Since your controller is declared (by <context:component-scan />) in the root context, <security:global-method-security /> should be declared there as well.

Upvotes: 3

Related Questions