2014-09-12 118 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