简体   繁体   中英

Spring Security - how I can enable Method Security annotations?

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

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:

When using controller interfaces (eg 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. 使用控制器接口(例如,用于AOP代理)时,请确保始终将所有映射注释(例如@RequestMapping@SessionAttributes )放在控制器接口而不是实现类上。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM