2014-09-12 117 views
1

我为我的RESTful web服务使用RequestHeaderAuthenticationFilter。但是,某些请求应该可供所有用户使用,并且不应该要求额外的标头。例如:Spring Security预认证匹配器

/articles/**  requires header 
/items/**   requires header 
/cmd/**    does not require header 

所以,我想用我的春季安全配置如下:

@Override 
public void configure(HttpSecurity http) throws Exception { 
    http.authorizeRequests().antMatchers("/cmd/**").anonymous().and() 
     .addFilterBefore(securityFilter(), AbstractPreAuthenticatedProcessingFilter.class).authorizeRequests() 
     .antMatchers("/**").hasRole(DEFAULT_USER_ROLE); 
    http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); 
    http.csrf().disable(); 
    super.configure(http); 
} 

但是,这似乎并没有像预期的那样工作,因为如果我启动了以下要求:

GET /test-services/cmd/test 

它仍然需要头,因为它会引发以下异常:

SEVERE: Servlet.service() for servlet [CXFServlet] in context with path [/test-services] threw exception 
org.springframework.security.web.authentication.preauth.PreAuthenticatedCredentialsNotFoundException: Authenticated-User header not found in request. 
    at org.springframework.security.web.authentication.preauth.RequestHeaderAuthenticationFilter.getPreAuthenticatedPrincipal(RequestHeaderAuthenticationFilter.java:43) 
    at org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter.doAuthenticate(AbstractPreAuthenticatedProcessingFilter.java:103) 
    at org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter.doFilter(AbstractPreAuthenticatedProcessingFilter.java:91) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) 
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:110) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) 
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:57) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) 
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) 
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) 
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192) 
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160) 
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:344) 
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:261) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) 
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219) 
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106) 
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:503) 
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:136) 
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:74) 
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:610) 
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88) 
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:516) 
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1015) 
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:652) 
    at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:222) 
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1575) 
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1533) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) 
    at java.lang.Thread.run(Thread.java:745) 

是否可以仅在特定情况下应用过滤器?

回答

0

在改变过滤器链代替我改变了所有与安全相关的API的情况下,因此,例如我现在有:

/api/secured/articles/**  requires header 
/api/secured/items/**   requires header 
/api/cmd/**      does not require header 

现在我申请的DelegatingFilterProxy只对/api/secured*请求。

1

如果受保护的URL模式的数量足够小,则只能为它们注册过滤器,并将/cmd/**排除。虽然这不是很好的解决方案。

其他可能的解决方案可能是编写我们的过滤器,它将从过滤中排除特定的URL,并为其他人调用原始过滤器。做一些像here

public void doFilter(ServletRequest request,ServletResponse response,FilterChain chain) 
    throws IOException, ServletException { 
    String url = request.getRequestURL().toString(); 
    if (matchExcludePatterns(url)) { 
     chain.doFilter(request, response); 
     return; 
    } 
    // call your filter 
} 
+0

我尝试了第二种方法,但它似乎不工作,也许是因为我不知道如何调用过滤器。我尝试写:'新的DelegatingFilterProxy()。doFilter(request,response,chain);'但这似乎并没有办法。 – g00glen00b 2014-09-16 06:32:25