【问题标题】:@Secured does not work in controller, but intercept-url seems to be working fine@Secured 在控制器中不起作用,但拦截 URL 似乎工作正常
【发布时间】:2011-10-02 19:51:55
【问题描述】:

看起来我的@Controller 中的@Secured on 方法没有被读取。当使用基于 sec:intercept-url 的安全过滤时,这似乎工作得很好。以下代码导致 Spring Security 给我这个日志条目:

调试:org.springframework.security.web.access.intercept.FilterSecurityInterceptor - 公共对象 - 未尝试身份验证

web.xml

上下文配置位置 /WEB-INF/spring/root-context.xml

<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<!-- Processes application requests -->
<servlet>
    <servlet-name>appServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/spring/appServlet/servlet-context.xml
        </param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

<!-- Filter security -->
<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>

servlet-context.xml 包含 viewResolvers 的配置和所有编组。此配置是注释驱动的。

root-context.xml

    <sec:global-method-security secured-annotations="enabled" />

<sec:http auto-config="true">
    <sec:http-basic/>
</sec:http>

<!-- Declare an authentication-manager to use a custom userDetailsService -->
<sec:authentication-manager>
    <sec:authentication-provider
        user-service-ref="userDetailsService">
        <sec:password-encoder ref="passwordEncoder" />
    </sec:authentication-provider>
</sec:authentication-manager>

<bean
    class="org.springframework.security.authentication.encoding.PlaintextPasswordEncoder"
    id="passwordEncoder" />
<sec:user-service id="userDetailsService">
    <sec:user name="john" password="john" authorities="ROLE_USER, ROLE_ADMIN" />
    <sec:user name="jane" password="jane" authorities="ROLE_USER" />
</sec:user-service>

PingController.java

@Controller
public class PingController {

    @Secured("ROLE_ADMIN")
    @RequestMapping(value = "/ping", method = RequestMethod.GET)
    public void ping() {
    }

}

这似乎与我使用的身份验证方法没有任何关系,因此可以忽略 basic-http-tag。

我有这样的想法,@Secured 不起作用,因为它在另一个上下文中使用,而不是在其中配置安全性的 root-context.xml。我试图将此配置移动到 servlet-context.xml,但它似乎没有到达 springSecurityFilterChain。对这个问题和我的理论有什么想法吗?

【问题讨论】:

    标签: spring spring-mvc spring-security spring-annotations


    【解决方案1】:

    Spring Security FAQ(强调我的)。如果您将切入点应用到服务层,您只需在应用的安全上下文中设置 &lt;global-method-security&gt;

    在 Spring Web 应用程序中,应用程序上下文包含 调度程序 servlet 的 Spring MVC bean 通常与 主要应用程序上下文。它通常定义在一个名为 myapp-servlet.xml,其中“myapp”是分配给 Spring 的名称 web.xml 中的 DispatcherServlet。一个应用程序可以有多个 DispatcherServlets,每个都有自己独立的应用程序上下文。 这些“子”上下文中的 bean 对其余部分不可见 应用。 “父”应用程序上下文由 您在 web.xml 中定义并且对所有人可见的 ContextLoaderListener 子上下文。这个父上下文通常是你定义的地方 您的安全配置,包括 元素)。因此,任何应用于方法的安全约束 这些 web bean 不会被强制执行,因为这些 bean 不可见 来自 DispatcherServlet 上下文。您需要移动 声明到 web 上下文或移动 您希望将 bean 保护到主应用程序上下文中。

    通常我们建议在服务中应用方法安全性 层而不是单个 Web 控制器。

    【讨论】:

    • 这就是一个 Web 应用程序可以拥有任意数量的界面的方式。将它应用到服务层是最好的选择,但这样做也有一个缺点——在大多数情况下,会应用不必要的映射。
    • 能否刷新链接地址?
    【解决方案2】:

    你是对的,&lt;global-method-security&gt; 是在每个上下文的基础上应用的。但是,您不需要将整个安全配置移动到 servlet-context.xml,只需向其中添加一个 &lt;global-method-security&gt; 元素即可。

    【讨论】:

    • 正确。非常感谢,@axtavt!
    • 如果您使用Java Config方式,您可以在扩展WebMvcConfigurerAdapter的配置类中添加注解@EnableGlobalMethodSecurity
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-19
    • 2016-03-04
    • 1970-01-01
    • 1970-01-01
    • 2014-02-11
    相关资源
    最近更新 更多