Reputation: 35961
There is lot of similar questions at StackOverflow, but I can't find any answered :(
I have web.xml like:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring-security.xml
</param-value>
</context-param>
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-web.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<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>
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
and trying to configure method security with annotations. As I see it must be done by <sec:global-method-security pre-post-annotations="enabled"/>
, placed at same context as other components, spring-web.xml
at my case. So I have following spring-web.xml
:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:sec="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/security
http://www.springframework.org/schema/security/spring-security-3.0.xsd"
default-autowire="byName">
<context:component-scan base-package="com.cleanplates.apiserv"/>
<sec:global-method-security pre-post-annotations="enabled"/>
</beans>
and spring-security.xml
:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:sec="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/security
http://www.springframework.org/schema/security/spring-security-3.0.xsd">
<bean id="springSecurityFilterChain" class="org.springframework.security.web.FilterChainProxy">
<sec:filter-chain-map path-type="ant">
<sec:filter-chain pattern="/**"
filters="
usernamePasswordProcessingFilter,
rememberMeFilter,
anonymousProcessingFilter,
exceptionTranslationFilter,
filterInvocationInterceptor"/>
</sec:filter-chain-map>
</bean>
<bean id="accessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased">
<property name="decisionVoters">
<list>
<bean class="org.springframework.security.access.vote.RoleVoter"/>
</list>
</property>
</bean>
<bean id="anonymousProcessingFilter"
class="org.springframework.security.web.authentication.AnonymousAuthenticationFilter">
<property name="key" value="********"/>
<property name="userAttribute">
<bean class="org.springframework.security.core.userdetails.memory.UserAttribute">
<property name="authoritiesAsString">
<list>
<value>ROLE_ANONYMOUS</value>
</list>
</property>
<property name="password" value="none"/>
</bean>
</property>
</bean>
<bean id="usernamePasswordProcessingFilter" class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
<property name="filterProcessesUrl" value="/auth/password"/>
<property name="usernameParameter" value="username"/>
<property name="passwordParameter" value="password"/>
<property name="authenticationManager" ref="authenticationManager"/>
</bean>
<bean id="rememberMeFilter" class="org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter">
<property name="rememberMeServices" ref="rememberMeServices"/>
<property name="authenticationManager" ref="authenticationManager" />
</bean>
<bean id="rememberMeServices" class="org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices">
<property name="userDetailsService" ref="myUserDetailsService"/>
<property name="key" value="*******"/>
<property name="alwaysRemember" value="true"/>
</bean>
<bean id="rememberMeAuthenticationProvider" class="org.springframework.security.authentication.RememberMeAuthenticationProvider">
<property name="key" value="******"/>
</bean>
<bean id="exceptionTranslationFilter" class="org.springframework.security.web.access.ExceptionTranslationFilter">
<property name="authenticationEntryPoint">
<bean class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint"/>
</property>
</bean>
<bean id="filterInvocationInterceptor"
class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="securityMetadataSource">
<sec:filter-security-metadata-source>
<sec:intercept-url pattern="/**" access="ROLE_ANONYMOUS,ROLE_USER" method="GET"/>
<sec:intercept-url pattern="/**" access="ROLE_ADMIN" method="POST"/>
<sec:intercept-url pattern="/**" access="ROLE_ADMIN" method="PUT"/>
<sec:intercept-url pattern="/**" access="ROLE_ADMIN" method="DELETE"/>
</sec:filter-security-metadata-source>
</property>
<property name="accessDecisionManager" ref="accessDecisionManager"/>
</bean>
<bean id="authenticationManager" class="org.springframework.security.authentication.ProviderManager">
<property name="providers">
<list>
<bean class="org.springframework.security.authentication.AnonymousAuthenticationProvider">
<property name="key" value="***"/>
</bean>
<bean class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
<property name="saltSource">
<bean class="org.springframework.security.authentication.dao.ReflectionSaltSource">
<property name="userPropertyToUse" value="salt"/>
</bean>
</property>
<property name="userDetailsService" ref="myUserDetailsService"/>
<property name="passwordEncoder" ref="passwordEncoder"/>
</bean>
</list>
</property>
</bean>
<bean id="myUserDetailsService" class=".UserDetailsServiceImpl">
</bean>
<bean id="passwordEncoder" class="org.springframework.security.authentication.encoding.Md5PasswordEncoder">
</bean>
</beans>
The problem that after adding <sec:global-method-security
all controllers stop working. And I have following in logs:
PageNotFound:noHandlerFound:947 - No mapping found for HTTP request with URI [/some/page] in DispatcherServlet with name 'spring'
Everything is working when i remove this global-security
element. If i'm adding it into spring-security.xml
- nothing changes. Seems that it's not used, because methods annotated with @PreAuthorize("hasRole('ROLE_ADMIN')")
(or any other role) are accessible by anyone.
PS I'm using Spring 3.0.5.RELEASE and Spring Security 3.0.5.RELEASE
Upvotes: 5
Views: 10299
Reputation: 1481
After you enable <sec:global-method-security>
spring security creates proxies for your controllers. spring-mvc can't find annotations like @RequestMapping
on bean in this case. If you want to use security annotations on your controllers you should extract interface of controller and put mvc annotations on it.
Spring documentation contains following note about this:
NOTE: When using controller interfaces (e.g. for AOP proxying), make sure to consistently put all your mapping annotations - such as
@RequestMapping
and@SessionAttributes
- on the controller interface rather than on the implementation class.
Upvotes: 2