繁体   English   中英

使用Spring WS获取SOAP Header的内容

[英]Getting content of a SOAP Header using Spring WS

我正在尝试构建一个端点,该端点将从客户端接收SOAP消息。 我收到的消息在soap标头中包含用户名和密码...

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns="http://www.company.com/Application">
    <soapenv:Header  xmlns:wsse="http://__________.xsd">
        <wsse:Security >
            <wsse:UsernameToken>
                <wsse:Username>username</wsse:Username>
                <wsse:Password>password</wsse:Password>
            </wsse:UsernameToken>
        </wsse:Security>

   </soapenv:Header>
   <soapenv:Body>

我正在使用Spring WS-显而易见的解决方案是在web.xml中创建一个过滤器,该过滤器将完全绕过Spring WS,解析SOAP消息,提取用户名和密码,然后继续到Spring WS,它将再次解析SOAP。

有没有一种方法可以在不绕过Spring WS的情况下获取标头的内容?

我试过在sws:interceptors添加一个bean:

<sws:interceptors>

    <!-- extract Security details from Header -->
    <bean class="com.company.application.service.SecurityInterceptorService" />

    <!-- log full Body of request -->
    <bean class="org.springframework.ws.server.endpoint.interceptor.PayloadLoggingInterceptor"/>

    <!-- validate Request against XSD to make sure it's a valid request -->
    <bean id="CompanyApplication" class="com.company.application.interceptor.ValidatingInterceptor">
        <property name="schema" value="/WEB-INF/_______________.xsd" />
        <property name="validateRequest" value="true" />
        <property name="validateResponse" value="true" />
    </bean>

</sws:interceptors>

然后实现该类:

public class SecurityInterceptorService implements EndpointInterceptor {


    @Override
    public boolean handleRequest(MessageContext messageContext, Object endpoint) throws Exception {

        System.out.println("---------------");
        System.out.println("handleRequest")                                             ;
        System.out.println("---------------");


        return true;
    }

    @Override
    public boolean handleResponse(MessageContext messageContext, Object endpoint) throws Exception {

        System.out.println("---------------");
        System.out.println("handleResponse");
        System.out.println("---------------");



        return true;
    }

    @Override
    public boolean handleFault(MessageContext messageContext, Object endpoint) throws Exception {

        System.out.println("---------------");
        System.out.println("handleFault");
        System.out.println("---------------");


        return true;
    }

    @Override
    public void afterCompletion(MessageContext messageContext, Object endpoint, Exception ex) throws Exception {

        System.out.println("---------------");
        System.out.println("afterCompletion");
        System.out.println("---------------");

    }



}

endpoint仅包含有关handleRequestendpoint数据,并且在调试模式下遍历messageContext内的许多层之后,我似乎无法发现标头的内容。

我在messageContext寻找的内容是什么,如果是,如何访问它?

messageContext对象中,您可以检索请求或响应(在您的情况下,我想您需要该请求)。

请求/响应基本上是WebServiceMessage 如果检查webServiceMessage,将看到该对象可以转换为SoapMessage 从soap消息中,您现在可以获取soap标头。

WebServiceMessage webServiceMessageRequest = messageContext_.getRequest();
SoapMessage soapMessage = (SoapMessage) webServiceMessageRequest;
SoapHeader soapHeader = soapMessage.getSoapHeader()

之后,您可能想要获取对象并将其转换为DOMSource对象,然后获取Node对象,这使信息检索变得更加容易。

Source bodySource = soapHeader .getSource();
DOMSource bodyDomSource = (DOMSource) bodySource;
Node bodyNode = _bodyDomSource.getNode();

如果您使用的是spring-boot,则可以使用以下配置:

@EnableWs
@Configuration
public class WebServiceConfig extends WsConfigurerAdapter {

  @Override
  public void addInterceptors(List<EndpointInterceptor> interceptors) {
    PayloadValidatingInterceptor validatingInterceptor = new PayloadValidatingInterceptor();
    validatingInterceptor.setValidateRequest(true);
    validatingInterceptor.setValidateResponse(true);
    validatingInterceptor.setXsdSchema(resourceSchema());
    interceptors.add(validatingInterceptor);
  }

  @Bean
  public ServletRegistrationBean messageDispatcherServlet(ApplicationContext applicationContext) {
    MessageDispatcherServlet servlet = new MessageDispatcherServlet();
    servlet.setApplicationContext(applicationContext);
    servlet.setTransformWsdlLocations(true);
    return new ServletRegistrationBean(servlet, "/api/*");
  }

  @Bean(name = "registros")
  public DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema countriesSchema) {
    DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition();
    wsdl11Definition.setPortTypeName("ResourcePort");
    wsdl11Definition.setLocationUri("/api");
    wsdl11Definition.setTargetNamespace("http://resource.com/schema");
    wsdl11Definition.setSchema(resourceSchema());
    return wsdl11Definition;
  }

  @Bean
  public XsdSchema resourceSchema() {
    return new SimpleXsdSchema(new ClassPathResource("registro.xsd"));
  }
}

在此示例中, addInterceptors方法是重要的方法,其他方法3是公开WSDL API的基础。

也许对其他人有用。

没有简单的方法可以使用Spring-ws解编Soap头( 目前不支持 ),但是,您可以在@PayloadRoot注释方法中访问SoapHeaderElement,并使用JAXB进行解编过程。

@Endpoint
public class SubmitEndpoint implements EndpointInterface {

    private static final String NAMESPACE_URI = "http://www.example.com/namespace";

    private Security unmarshallSecurityFromSoapHeader(SoapHeaderElement header) {
        Security security = null;
        try {

            JAXBContext context = JAXBContext.newInstance(Security.class);
            Unmarshaller unmarshaller = context.createUnmarshaller();
            security = (Security) unmarshaller.unmarshal(header.getSource());

        } catch (JAXBException e) {
            e.printStackTrace();
        }
        return security;
    }

    @PayloadRoot(namespace = NAMESPACE_URI, localPart = "submit")
    @ResponsePayload
    public SubmitResponse submit(@RequestPayload Submit submit, @SoapHeader(
            value = "{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}Security") SoapHeaderElement wsseSecurityHeader) throws JAXBException {


        Security security = unmarshallSecurityFromSoapHeader(wsseSecurityHeader);

    }
}

安全性

@Getter
@Setter
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(namespace = Security.SECURITY_NS, name = "Security")
public class Security {

    public static final String SECURITY_NS = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";

    @XmlElement(namespace = SECURITY_NS, name = "UsernameToken")
    private UsernameToken usernameToken;

}

UsernameToken.java

@Getter
@Setter
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(namespace = Security.SECURITY_NS, name = "UsernameToken")
public class UsernameToken {

    @XmlElement(name = "Username", namespace = Security.SECURITY_NS)
    private String username;

    @XmlElement(name = "Password", namespace = Security.SECURITY_NS)
    private String password;

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM