[英]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
仅包含有关handleRequest
内endpoint
数据,并且在调试模式下遍历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.