Skip to content

Instantly share code, notes, and snippets.

@m-wrona
Last active November 9, 2020 08:40
Show Gist options
  • Save m-wrona/4c51fccd3dda1368209a2f0ce8dd06dd to your computer and use it in GitHub Desktop.
Save m-wrona/4c51fccd3dda1368209a2f0ce8dd06dd to your computer and use it in GitHub Desktop.
WebService - Preemptive auth
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ws.client.WebServiceClientException;
import org.springframework.ws.client.support.interceptor.ClientInterceptor;
import org.springframework.ws.context.MessageContext;
import org.springframework.ws.transport.WebServiceConnection;
import org.springframework.ws.transport.context.TransportContext;
import org.springframework.ws.transport.context.TransportContextHolder;
import org.springframework.ws.transport.http.HttpUrlConnection;
import java.util.Optional;
import static org.apache.tomcat.util.codec.binary.Base64.encodeBase64String;
/**
* Preemptive basic authorization.
* Client adds "Authorization: Basic BASE_64_ENCODED_STRING" header to all out-going requests
*/
public final class PreemptiveAuth implements ClientInterceptor {
private static final String HEADER_AUTHORIZATION = "Authorization";
private static final String BASIC_AUTH = "Basic ";
private static final char BASIC_AUTH_SEPARATOR = ':';
private static final boolean CONTINUE_PROCESSING = true;
private final Logger LOGGER = LoggerFactory.getLogger(PreemptiveAuth.class);
private final String userName;
private final String password;
@Override
public boolean handleRequest(MessageContext messageContext) throws WebServiceClientException {
return getConnection(TransportContextHolder.getTransportContext().getConnection())
.map(httpConnection -> appendAuthorization(httpConnection))
.orElseGet(() -> CONTINUE_PROCESSING);
}
/**
* Get connection from context
*
* @param connection current SOAP connection
* @return optional connection
*/
private Optional<HttpUrlConnection> getConnection(WebServiceConnection connection) {
if (connection instanceof HttpUrlConnection) {
return Optional.of((HttpUrlConnection) connection);
} else {
LOGGER.error("Preemptive auth skipped due to SOAP connection that doesn't implement: {}", HttpUrlConnection.class);
return Optional.empty();
}
}
/**
* Append basic auth header to given connection
*
* @param connection connection where header should be appended to
* @return flag indicating whether processing should be continued
*/
private boolean appendAuthorization(HttpUrlConnection connection) {
LOGGER.debug("Preemptive auth - applying auth - user: {}, pass length: {}", userName, password.length());
connection
.getConnection()
.addRequestProperty(
HEADER_AUTHORIZATION, BASIC_AUTH + encodeBase64String(getCredentials().getBytes())
);
return CONTINUE_PROCESSING;
}
/**
* Get credentials
*
* @return non-empty string
*/
private String getCredentials() {
return userName + BASIC_AUTH_SEPARATOR + password;
}
@Override
public boolean handleResponse(MessageContext messageContext) throws WebServiceClientException {
return CONTINUE_PROCESSING;
}
@Override
public boolean handleFault(MessageContext messageContext) throws WebServiceClientException {
return CONTINUE_PROCESSING;
}
@Override
public void afterCompletion(MessageContext messageContext, Exception e) throws WebServiceClientException {
//empty
}
public PreemptiveAuth(String userName, String password) {
this.userName = userName;
this.password = password;
}
}
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
import org.springframework.ws.client.support.interceptor.ClientInterceptor;
import org.springframework.ws.soap.SoapMessageFactory;
import org.springframework.ws.soap.saaj.SaajSoapMessageFactory;
@Configuration
public class WebServiceConfig {
@Value("${webservice.modelPackages}")
private String[] modelPackages;
@Value("${webservice.user}")
private String userName;
@Value("${webservice.password}")
private String password;
@Bean
public SoapMessageFactory messageFactory() {
return new SaajSoapMessageFactory();
}
@Bean
public Jaxb2Marshaller marshaller() {
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setPackagesToScan(modelPackages);
return marshaller;
}
@Bean
public SomeWebService incidentWebService(Jaxb2Marshaller marshaller, SoapMessageFactory messageFactory) {
SomeWebService client = new SomeWebService();
client.setMarshaller(marshaller);
client.setUnmarshaller(marshaller);
client.setMessageFactory(messageFactory);
client.setInterceptors(new ClientInterceptor[]{
new PreemptiveAuth(userName, password)
});
return client;
}
}
@m-wrona
Copy link
Author

m-wrona commented Jun 15, 2016

Sample code for hooking up preemptive auth to web services (SOAP) using Spring.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment