2015-09-24 86 views
1

我在Spring應用程序上使用httpBasic身份驗證使用多個可用的SOAP Web服務,並且我需要在其中一個WS-Security上使用WS-Security來允許使用以下Soap進行身份驗證頭。Spring WS:如何將攔截器應用到特定端點

<soap:Header><wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" soap:mustUnderstand="1"> 
    <wsse:UsernameToken xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="UsernameToken-1"> 
    <wsse:Username>username</wsse:Username> 
    <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">password</wsse:Password> 
    </wsse:UsernameToken> 
</wsse:Security></soap:Header> 

當前WSConfiguration根據https://github.com/spring-projects/spring-boot/blob/master/spring-boot-samples/spring-boot-sample-ws/根據http://spring.io/blog/2013/07/03/spring-security-java-config-preview-web-security/給像

@EnableWs 
@Configuration 
public class WebServiceConfig extends WsConfigurerAdapter { 

    @Bean 
    public ServletRegistrationBean dispatcherServlet(ApplicationContext applicationContext) { 
     MessageDispatcherServlet servlet = new MessageDispatcherServlet(); 
     servlet.setApplicationContext(applicationContext); 
     return new ServletRegistrationBean(servlet, "/services/*"); 
    } 

    @Bean(name = "SOAP1") 
    public DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema soap1) { 
     DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition(); 
     wsdl11Definition.setPortTypeName("Soap1"); 
     wsdl11Definition.setLocationUri("/soap1/"); 
     wsdl11Definition.setTargetNamespace("http://mycompany.com/hr/definitions"); 
     wsdl11Definition.setSchema(soap1); 
     return wsdl11Definition; 
    } 

    @Bean 
    public XsdSchema soap1() { 
     return new SimpleXsdSchema(new ClassPathResource("META-INF/schemas/hr.xsd")); 
    } 

} 

和Web安全做看起來像這樣

@EnableWebSecurity 
@Configuration 
public class CustomWebSecurityConfigurerAdapter extends 
    WebSecurityConfigurerAdapter { 
    @Autowired 
    public void configureGlobal(AuthenticationManagerBuilder auth) { 
    auth 
     .inMemoryAuthentication() 
     .withUser("user1") 
      .password("password") 
      .roles("SOAP1") 
      .and() 
     .withUser("user2") 
      .password("password") 
      .roles("SOAP2"); 
    } 

    @Override 
    protected void configure(HttpSecurity http) throws Exception { 
    http 
     .authorizeUrls() 
     .antMatchers("/soap/soap1").hasRole("SOAP1") 
     .antMatchers("/soap/soap2").hasRole("SOAP2") 
     .anyRequest().authenticated() 
     .and().httpBasic(); 
    } 
} 

一些搜索後,我發現WSS4J提供UsernameToken身份驗證,但無法弄清楚如何使用它。我想要做的是以下 https://sites.google.com/site/ddmwsst/ws-security-impl/ws-security-with-usernametoken 但沒有帶有bean定義的XML文件。

我打算做:

  • 創建回調處理程序。
  • 創建Wss4jSecurityInterceptor,設置「setValidationActions」到「用戶名令牌」,「setValidationCallbackHandler」我的回調處理程序,然後通過添加它覆蓋在我的WebServiceConfigaddInterceptors

(我試過類似的東西,但我才意識到我的回調是使用的方法已過時)

問題:即使它的工作原理,它會接着適用於我的「WebServiceConfig」所有的web服務。

更新:

的實施工作,但預期它被應用到我所有的網絡服務。我如何才能將攔截器添加到1個Web服務?

之後,我在WebServiceConfig添加

@Bean 
    public Wss4jSecurityInterceptor wss4jSecurityInterceptor() throws IOException, Exception{ 
     Wss4jSecurityInterceptor interceptor = new Wss4jSecurityInterceptor(); 
     interceptor.setValidationActions("UsernameToken"); 
     interceptor.setValidationCallbackHandler(new Wss4jSecurityCallbackImpl()); 

    return interceptor; 
} 

@Override 
public void addInterceptors(List<EndpointInterceptor> interceptors) { 
    try { 
     interceptors.add(wss4jSecurityInterceptor()); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 

回答

3

對不起的代碼,我完全忘了回答這個問題,但在情況下,它可以幫助別人:

我們得到了它創建一個新的SmartEndpointInterceptor工作,並它僅適用於我們的端點:

public class CustomSmartEndpointInterceptor extends Wss4jSecurityInterceptor implements SmartEndpointInterceptor { 

    //CustomEndpoint is your @Endpoint class 
    @Override 
    public boolean shouldIntercept(MessageContext messageContext, Object endpoint) { 
     if (endpoint instanceof MethodEndpoint) { 
      MethodEndpoint methodEndpoint = (MethodEndpoint)endpoint; 
      return methodEndpoint.getMethod().getDeclaringClass() == CustomEndpoint.class; 
     } 
     return false; 
    } 
} 

不是添加WSS4J豆到WebServiceConfig,我們增加了我們的SmartEndpointInterceptor:

@Configuration 
public class SoapWebServiceConfig extends WsConfigurationSupport { 

    //Wss4jSecurityCallbackImpl refers to an implementation of https://sites.google.com/site/ddmwsst/ws-security-impl/ws-security-with-usernametoken 
    @Bean 
    public CustomSmartEndpointInterceptor customSmartEndpointInterceptor() { 
     CustomSmartEndpointInterceptor customSmartEndpointInterceptor = new CustomSmartEndpointInterceptor(); 
     customSmartEndpointInterceptor.setValidationActions("UsernameToken"); 
     customSmartEndpointInterceptor.setValidationCallbackHandler(new Wss4jSecurityCallbackImpl(login, pwd)); 
     return customSmartEndpointInterceptor; 
    } 

    [...] 
} 

希望這是很清楚:)

+0

我遇到了同樣的問題。我試着完全按照你上面提到的方式做,但shouldIntercept方法永遠不會被擊中。 – lastmannorth

+0

您是否遵循https://spring.io/guides/gs/producing-web-service/#_configure_web_service_beans? 這是我正在運行的配置。您應該有一個擴展WsConfigurationSupport的類,這就是您應該添加customSmartEndpointInterceptor Bean的地方。 –

+0

有點晚了,但感謝它的工作! – lastmannorth