Spring Boot文档阅读笔记-3 Ways to Add Custom Header in Spring SOAP Request

Posted IT1995

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring Boot文档阅读笔记-3 Ways to Add Custom Header in Spring SOAP Request相关的知识,希望对你有一定的参考价值。

本篇博文使用3种不同的方法,在Spring SOAP(Simple Object Access Protocol)上添加自定义头信息。头信息一般是服务端用于身份验证的。

SOAP头信息在SWDL文档中是不会提及的,这需要程序员手动在请求上添加头信息。这里可以使用interceptor用于添加头信息,也可以在WebServiceMessageCallback中重写dowithMessage()方法上做,也可以在JAXB Marshaller中添加头信息。

下面是一个简单的SOAP请求的XML头信息。

<soapenv:Header>
    <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
        <wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
            <wsse:Username>abc</wsse:Username>
            <wsse:Password>abc</wsse:Password>
        </wsse:UsernameToken>
    </wsse:Security>
</soapenv:Header>

SOAP Web Service Adapter

在添加头信息前,首先要有一个SOAP的适配器,如下代码:

BlzServiceAdpter.java

public class BlzServiceAdapter extends WebServiceGatewaySupport 

	private static final Logger logger = LoggerFactory.getLogger(BlzServiceAdapter.class);

	public GetBankResponseType getBank(String url, Object requestPayload)
		WebServiceTemplate webServiceTemplate = getWebServiceTemplate();
		JAXBElement res = null;
		try 
			res = (JAXBElement) webServiceTemplate.marshalSendAndReceive(url, requestPayload);
		catch(SoapFaultClientException ex)
			logger.error(ex.getMessage());
		
		return res.getValue();
	

Using TransformerFactory to Transform XML to Header

首先在application.properties文件中添加对应的头数据,和用户名密码

soap.auth.header=<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"><wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"><wsse:Username>%(loginuser)</wsse:Username><wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">%(loginpass)</wsse:Password></wsse:UsernameToken></wsse:Security>
soap.auth.username=testuser
soap.auth.password=testpass

然后getBank中读取application.properties中关于soap头的信息,并将头信息设置到webServiceTemplate中

private static final Logger logger = LoggerFactory.getLogger(BlzServiceAdapter.class);

@Autowired
private Environment environment;

public GetBankResponseType getBank(String url, Object requestPayload)
	WebServiceTemplate webServiceTemplate = getWebServiceTemplate();
	JAXBElement res = null;
	try 
		res = (JAXBElement) webServiceTemplate.marshalSendAndReceive(url, requestPayload, new WebServiceMessageCallback() 

			@Override
			public void doWithMessage(WebServiceMessage message) 
				try 
					SoapHeader soapHeader = ((SoapMessage) message).getSoapHeader();
					Map mapRequest = new HashMap();

					mapRequest.put("loginuser", environment.getProperty("soap.auth.username"));
					mapRequest.put("loginpass", environment.getProperty("soap.auth.password"));
					StringSubstitutor substitutor = new StringSubstitutor(mapRequest, "%(", ")");
					String finalXMLRequest = substitutor.replace(environment.getProperty("soap.auth.header"));
					StringSource headerSource = new StringSource(finalXMLRequest);
					Transformer transformer = TransformerFactory.newInstance().newTransformer();
					transformer.transform(headerSource, soapHeader.getResult());
					logger.info("Marshalling of SOAP header success.");
				 catch (Exception e) 
					logger.error("error during marshalling of the SOAP headers", e);
				
			
		);
	catch (SoapFaultClientException e)
		logger.error("Error while invoking session service : " + e.getMessage());
		return null;
	
	return res.getValue();

这里有一点要注意,如果要在header中的security结点上添加一个新的结点,这个方式就会报错The markup in the document following the root element must be well-formed,解决办法是手动加一个SOAPHeaderElement在头信息中。

Using SOAPElement to Header Manually

在doWithMessage()函数中实现,首先手动创建SOAPHeaderElement及SOAPElement,然后再把这个添加到SOAPHeader上。

TokenHeaderRequestCallbak.java

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.client.core.WebServiceMessageCallback;
import org.springframework.ws.soap.saaj.SaajSoapMessage;

import javax.xml.soap.*;

public class TokenHeaderRequestCallback implements WebServiceMessageCallback 

    private static final Logger logger = LoggerFactory.getLogger(SessionHeaderRequestCallback.class);

    private String username;
    private String password;

    public TokenHeaderRequestCallback(String username, String password)
        this.username = username;
        this.password = password;
    

    public void doWithMessage(WebServiceMessage message) 

        try 

            SaajSoapMessage saajSoapMessage = (SaajSoapMessage)message;

            SOAPMessage soapMessage = saajSoapMessage.getSaajMessage();

            SOAPPart soapPart = soapMessage.getSOAPPart();

            SOAPEnvelope soapEnvelope = soapPart.getEnvelope();

            SOAPHeader soapHeader = soapEnvelope.getHeader();

            Name headerElementName = soapEnvelope.createName(
                    "Security",
                    "wsse",
                    "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
            );
            SOAPHeaderElement soapHeaderElement = soapHeader.addHeaderElement(headerElementName);

            SOAPElement usernameTokenSOAPElement = soapHeaderElement.addChildElement("UsernameToken", "wsse");

            SOAPElement userNameSOAPElement = usernameTokenSOAPElement.addChildElement("Username", "wsse");
            logger.info(this.username);
            userNameSOAPElement.addTextNode(this.username);

            SOAPElement passwordSOAPElement = usernameTokenSOAPElement.addChildElement("Password", "wsse");

            passwordSOAPElement.addTextNode(this.password);

            soapMessage.saveChanges();
         catch (SOAPException soapException) 
            throw new RuntimeException("TokenHeaderRequestCallback", soapException);
        
    

Using JAXB Marshaller to Add Header

这种方式比较简单,在JAXB marshaller上创建SOAP header就可以了。如下代码:

@Override
public void doWithMessage(WebServiceMessage message) 
	try 
		SoapHeader soapHeader = ((SoapMessage) message).getSoapHeader();
		ObjectFactory factory = new ObjectFactory();
		AuthSoapHeaders authSoapHeaders =
				factory.createAuthSoapHeaders();
		authSoapHeaders.setUsername("testuser");
		authSoapHeaders.setPassword("testpass");
		JAXBElement headers =
				factory.createAuthSoapHeaders(AuthSoapHeaders);
		JAXBContext context = JAXBContext.newInstance(AuthSoapHeaders.class);
		Marshaller marshaller = context.createMarshaller();
		marshaller.marshal(authSoapHeaders, soapHeader.getResult());
	 catch (Exception e) 
		logger.error("error during marshalling of the SOAP headers", e);
	

);

以上是关于Spring Boot文档阅读笔记-3 Ways to Add Custom Header in Spring SOAP Request的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot文档阅读笔记-how-to-implement-2-way-ssl-using-spring-boot

Spring Boot文档阅读笔记-Scheduling Tasks

Spring Boot文档阅读笔记-Scheduling Tasks

Spring Boot文档阅读笔记-Scheduling Tasks

Spring Boot文档阅读笔记-exception handling–@ExceptionHandler解析与实例

Spring Boot文档阅读笔记-CORS Support