我有一个相当简单的例子,我正在尝试将HTTP标头(而不是SOAP标头)添加到我使用Spring WebServiceTemplate
创建的请求中。
我已经定义了ClientInterceptor
我正在做的事情:
@Override
public boolean handleRequest(MessageContext messageContext) throws WebServiceClientException {
try {
TransportContext context = TransportContextHolder.getTransportContext();
HttpComponentsConnection connection = (HttpComponentsConnection) context.getConnection();
connection.addRequestHeader("Authorization", String.format("Bearer %s", someAccessToken));
} catch (IOException exception) {
// Do nothing
}
return true;
}
这是我配置扩展SomeClient
的{{1}}的方式:
WebServiceConfigurationSupport
但是没有添加@Bean
public SomeClient someClient() {
...
SomeClientImpl service = new SomeClientImpl();
service.setObjectFactory(new com.path.ObjectFactory());
service.setDefaultUri(someUri);
service.setMarshaller(marshaller);
service.setUnmarshaller(marshaller);
service.setxStreamMarshaller(xStreamMarshaller);
service.setInterceptors(new ClientInterceptor[]{wss4jSecurityInterceptor()});
service.setMessageSender(new HttpComponentsMessageSender());
service.setInterceptors(new ClientInterceptor[]{wss4jSecurityInterceptor(), addHttpHeaderInterceptor()});
return service;
}
@Bean
public ClientInterceptor addHttpHeaderInterceptor() {
return new AddHttpHeaderInterceptor(someAccessToken);
}
@Bean
public Wss4jSecurityInterceptor wss4jSecurityInterceptor() {
Wss4jSecurityInterceptor interceptor = new Wss4jSecurityInterceptor();
interceptor.setSecurementActions(securementAction);
interceptor.setSecurementUsername(securementUsername);
interceptor.setSecurementPassword(securementPassword);
interceptor.setSecurementPasswordType(WSConstants.PW_TEXT);
interceptor.setSecurementMustUnderstand(false);
return interceptor;
}
标头。我还尝试了Authorization
:
CustomMessageCallback
但似乎没有效果。我做错了什么,为什么没有添加public class CustomMessageCallback implements WebServiceMessageCallback {
private String headerKey;
private String headerValue;
public CustomMessageCallback(String headerKey, String headerValue) {
this.headerKey = headerKey;
this.headerValue = headerValue;
}
@Override
public void doWithMessage(WebServiceMessage webServiceMessage) throws IOException, TransformerException {
TransportContext context = TransportContextHolder.getTransportContext();
HttpComponentsConnection conn = (HttpComponentsConnection) context.getConnection();
HttpPost post = conn.getHttpPost();
post.addHeader(headerKey, headerValue);
}
}
标题?谢谢!
答案 0 :(得分:1)
使用HeadersAwareSenderWebServiceConnection
接口而不是实际的基础连接。
TransportContext context = TransportContextHolder.getTransportContext();
HeadersAwareSenderWebServiceConnection connection = (HeadersAwareSenderWebServiceConnection) context.getConnection();
connection.addRequestHeader("Authorization", String.format("Bearer %s", "********"));
现在,如果您升级/切换HTTP库,则无需更改此代码。
回答你关于你做错了什么的问题是你正在向错误的班级投掷。是的,您正在使用的类已弃用但它是您正在使用的库的一部分,您不能仅在不更改底层HTTP库的情况下转换为其他类。
答案 1 :(得分:0)
我过去做的是使用像这样的WebServiceMessageCallback
:
public class WsHttpHeaderCallback implements WebServiceMessageCallback
{
private String headerKey;
private String headerValue;
private String soapAction;
public WsHttpHeaderCallback(String headerKey, String headerValue, String soapAction)
{
super();
this.headerKey = headerKey;
this.headerValue = headerValue;
this.soapAction = soapAction;
validateRequiredFields();
}
public WsHttpHeaderCallback()
{
super();
}
@Override
public void doWithMessage(WebServiceMessage message) throws IOException, TransformerException
{
validateRequiredFields();
addRequestHeader(headerKey, headerValue);
if (StringUtils.hasText(this.soapAction))
{
AxiomSoapMessage axiomMessage = (AxiomSoapMessage) message;
axiomMessage.setSoapAction(this.soapAction);
}
}
private void validateRequiredFields()
{
if( !StringUtils.hasText(headerKey) )
{
throw new IllegalArgumentException("Impossibile proseguire. Passato HEADER HTTP con chiave non valida: ["+headerKey+"]");
}
if( !StringUtils.hasText(headerValue) )
{
throw new IllegalArgumentException("Impossibile proseguire. Passato HEADER HTTP con valore non valido: ["+headerValue+"]");
}
}
private void addRequestHeader(String headerKey, String headerValue)
{
TransportContext context = TransportContextHolder.getTransportContext();
WebServiceConnection connection = context.getConnection();
if (connection instanceof HttpComponentsConnection)
{
HttpComponentsConnection conn = (HttpComponentsConnection) connection;
HttpPost post = conn.getHttpPost();
post.addHeader(headerKey, headerValue);
}
else if( connection instanceof ClientHttpRequestConnection )
{
ClientHttpRequestConnection conn = (ClientHttpRequestConnection)connection;
conn.getClientHttpRequest().getHeaders().add(headerKey, headerValue);
}
}
}
然后我以这种方式使用它:
wsTemplate.marshalSendAndReceive(wsUrl, request, new WsHttpHeaderCallback(headerKey, headerValue, soapAction) );
通过这种方式,我成功设置了所有需要的HttpHeaders(在我的例子中只有一个:))
我希望它有用
安吉洛
答案 2 :(得分:0)
TL; DR 您的 messageSender 应该是 HttpComponentsMessageSender 的实例,而不是 HttpUrlConnectionMessageSender 。您还需要提供适当的凭据。
getConnection() TransportContext 的功能会返回 WebServiceConnection 的实施。 HttpUrlConnection 和 HttpComponentsConnection 都是相同的实现。所以基本上你得到了错误的连接类型,因此 ClassCastException 。ClientInterceptor 适用于自定义标头,但不适用于授权标头。为此,您的 HttpComponentsMessageSender 需要使用您的凭据进行配置。
正确的配置应该像this
@Value("${username}")
private String username;
@Value("${password}")
private String password;
@Bean
public SomeClient someClient() {
SomeClientImpl service = new SomeClientImpl();
service.setMessageSender();
//other configs
return service;
}
public HttpComponentsMessageSender getMessageSender(){
HttpComponentsMessageSender httpComponentsMessageSender = new HttpComponentsMessageSender();
httpComponentsMessageSender.setCredentials(getCredentials);
}
public UsernamePasswordCredentials getCredentials(){
return new UsernamePasswordCredentials(username, password);
}