2011-07-11 38 views
14

它看起来不像@Secured正在读取我的@Controller中的方法。当使用基于sec:intercept-url的安全过滤时,这似乎工作得很好。下面的代码导致的Spring Security给我这个日志条目:@Secured在控制器中不起作用,但拦截url似乎工作正常

DEBUG:org.springframework.security.web.access.intercept.FilterSecurityInterceptor - 公共对象 - 认证没有试图

网络。 XML

的contextConfigLocation /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和所有编组的配置。该配置由注释驱动。

根的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。对这个问题和我的理论有什么想法?

回答

23

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

+0

Spot on。非常感谢,@axtavt! – kareblak

+0

棒极了!谢谢:) – Athar

+1

如果您使用Java Config方式,您可以将注释'@ EnableGlobalMethodSecurity'添加到扩展了'WebMvcConfigurerAdapter'的配置类中。 – beat

9

请参阅Spring Security FAQ(强调我的)。如果将切入点应用于服务层,则只需在应用程序的安全上下文中设置<global-method-security>即可。

在一个Spring web应用程序,其保持 Spring MVC的豆用于调度的servlet应用上下文是常从 主应用程序上下文分离。它通常在名为 myapp-servlet.xml的文件中定义,其中“myapp”是分配给web.xml中的Spring DispatcherServlet的名称。一个应用程序可以有多个 DispatcherServlet,每个都有自己独立的应用程序上下文。 这些“子”上下文中的bean对于 应用程序的其余部分不可见。 “父”应用程序上下文由您在web.xml中定义的ContextLoaderListener加载,并且所有 子上下文都可见。此父上下文通常是您定义 安全配置的位置,包括 元素)。因此,应用于 中的方法的任何安全限制都将不会被强制执行,因为从DispatcherServlet上下文中无法看到该Bean的 。您需要将 声明移至Web上下文,或将需要保护的bean移至主应用程序上下文中。

通常我们会建议在服务层 上应用方法安全性,而不是在单独的Web控制器上。

+0

这就是一个Web应用程序如何可以拥有尽可能多的接口。将其应用于服务层是最佳选择,但这样做也有一个缺点 - 在大多数情况下会应用不必要的映射。 – kboom

+0

你能刷新链接地址吗? –

相关问题