java - Spring Security - 如何启用方法安全注释?

标签 java spring spring-security

StackOverflow 上有很多类似的问题,但我找不到任何答案:(

我有这样的 web.xml:

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

并尝试配置 method security带注释。正如我所见,它必须由 <sec:global-method-security pre-post-annotations="enabled"/> 完成,放置在与其他组件相同的上下文中,spring-web.xml在我的情况下。所以我有以下 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>

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>

加入<sec:global-method-security后的问题所有 Controller 停止工作。我在日志中有以下内容:

PageNotFound:noHandlerFound:947 - No mapping found for HTTP request with URI [/some/page] in DispatcherServlet with name 'spring'

当我删除这个 global-security 时一切正常元素。如果我将它添加到 spring-security.xml 中- 没有什么改变。似乎没有使用它,因为用 @PreAuthorize("hasRole('ROLE_ADMIN')") 注释的方法(或任何其他角色)任何人都可以访问。

PS 我正在使用 Spring 3.0.5.RELEASE 和 Spring Security 3.0.5.RELEASE

最佳答案

启用 <sec:global-method-security> 后spring security 为您的 Controller 创建代理。 spring-mvc 找不到像 @RequestMapping 这样的注释在这种情况下,在 bean 上。如果你想在你的 Controller 上使用安全注释,你应该提取 Controller 的接口(interface)并在其上放置 mvc 注释。 Spring 文档包含以下关于此的注释:

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.

关于java - Spring Security - 如何启用方法安全注释?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8229600/

相关文章:

java - 如何在 spring-batch 中计算 Tasket 中的项目?

java - gradle build 突然不起作用

grails - grails中两个 Action 签名之间的区别

java - Point3D在eclipse/JAVA中无法解析

java - 如何在Java中创建缓存来存储用户 session

java - JTable 渲染器中的按钮文本不可见。为什么?

spring - 秒 :authorize returning true for both isAuthenticated() and isAnonymous() in thymeleaf view

java - 计算 sin 30 的值

java - @ExceptionHandler 本地与全局

java - 使用 Spring Security 的 SiteMinder 注销