简体   繁体   中英

Consuming SOAP WS returns Error 401 unauthorized

I am trying to consume a SOAP webservice using spring-ws. I am able to successfully consume this web service from SOAP UI. However I receive an unauthorized exception:

org.springframework.ws.client.WebServiceTransportException: Unauthorized [401]
    at org.springframework.ws.client.core.WebServiceTemplate.handleError(WebServiceTemplate.java:699)

How do I successfully authenticate?

My code is as follows:

WebServiceTemplate configuration:

@Bean
    public WebServiceTemplate webServiceTemplate(Jaxb2Marshaller marshaller){
        WebServiceTemplate webServiceTemplate = new WebServiceTemplate();
        webServiceTemplate.setDefaultUri("http://ultron.illovo.net:9704/AdminService");
        webServiceTemplate.setMarshaller(marshaller);
        webServiceTemplate.setUnmarshaller(marshaller);

        Credentials credentials = new UsernamePasswordCredentials("biqa", "welcome1");

        HttpComponentsMessageSender messageSender = new HttpComponentsMessageSender();
        messageSender.setCredentials(credentials);
        messageSender.setReadTimeout(5000);
        messageSender.setConnectionTimeout(5000);
        webServiceTemplate.setMessageSender(messageSender);

        return webServiceTemplate;
    }

Client:

@Autowired

WebServiceTemplate webServiceTemplate;

public CallProcedureWithResultsResponse callProcedureWithResults(String procedureName){
    CallProcedureWithResults request = new CallProcedureWithResults();
    request.setProcedureName(procedureName);
    log.info("Calling procedure " + procedureName);

    CallProcedureWithResultsResponse response = (CallProcedureWithResultsResponse) webServiceTemplate.marshalSendAndReceive("http://ultron.illovo.net:9704/AdminService/AdminService", request);

    return response;
}

JUnit Test

@Test
    public void testWebService(){
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ObieeConfiguration.class);
        ObieeClient client = context.getBean(ObieeClient.class);
        CallProcedureWithResultsResponse response = client.callProcedureWithResults("GetOBISVersion()");
        client.printResponse(response);
        context.close();
    }

I managed to resolve this issue by doing the following:

Create a subclass of HttpUrlConnectionMessageSender as follows:

public class WebServiceMessageSenderWithAuth extends HttpUrlConnectionMessageSender {

    String user;
    String password;

    public WebServiceMessageSenderWithAuth(String user, String password) {
        this.user = user;
        this.password = password;
    }

    @Override
     protected void prepareConnection(HttpURLConnection connection) throws IOException { 
        BASE64Encoder enc = new BASE64Encoder(); 
        String userpassword = user+":"+password;
        String encodedAuthorization = enc.encode( userpassword.getBytes() ); 
        connection.setRequestProperty("Authorization", "Basic " + encodedAuthorization); 
        super.prepareConnection(connection); 
    } 

}

My client is defines as follows:

public class ObieeClient extends WebServiceGatewaySupport {

    private static final Logger log = LoggerFactory.getLogger(ObieeClient.class);

    public CallProcedureWithResultsResponse callProcedureWithResults(String procedureName, String webServiceURL){
        CallProcedureWithResults request = new CallProcedureWithResults();
        request.setProcedureName(procedureName);
        log.info("Calling procedure " + procedureName);

        CallProcedureWithResultsResponse response = (CallProcedureWithResultsResponse) ((JAXBElement) getWebServiceTemplate().marshalSendAndReceive(webServiceURL, request)).getValue();

        return response;
    }
}

And finally the client is configured to use the credentials by setting the message sender:

     Jaxb2Marshaller marshaller = new Jaxb2Marshaller();            marshaller.setContextPath("za.co.adaptit.smartdeployment.webservices.wsdl");

                //set up web service client
                ObieeClient client = new ObieeClient();
                client.setDefaultUri(host);
                client.setMarshaller(marshaller);
                client.setUnmarshaller(marshaller);
                client.setMessageSender(new WebServiceMessageSenderWithAuth("user", "password"));

response = client.callProcedureWithResults("NQSModifyMetadata('" + obieeObjectsXML +"')", server.getHost());

Hope this helps.

I run into the same issue and managed to resolved by defining a MessageSender with Credentials and then setting it to the client. I didn't have to create a custom MessageSender.

@Bean
public WebServiceMessageSender messageSender(Credentials credentials) throws Exception{
    HttpComponentsMessageSender messageSender = new HttpComponentsMessageSender();
    messageSender.setCredentials(credentials);
    return messageSender;
}

@Bean
public Credentials credentials(){
    UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(USERNAME, PASSWORD);
    return credentials;

}

use HttpsUrlConnectionMessageSender for secure Https connections. This is part of spring-ws-support dependency. Also, you can bypass various certificate issue by using HttpsUrlConnectonMessageSender, like certificate common name mis-matching.

Dont use BASE64Encoder, it is the class of sun.misc jar which is not much secure. use Base64 of java util present in java 1.8 and Base64 of apache for java version less then java 1.8

public class WebServiceMessageSenderWithAuth extends HttpsUrlConnectionMessageSender {

String user;
String password;

public WebServiceMessageSenderWithAuth(String user, String password) {
    this.user = user;
    this.password = password;
   }

@Override
 protected void prepareConnection(HttpURLConnection connection) throws IOException { 

    String userpassword = user+":"+password;
    String encodedAuthorization = Base64.encode( userpassword.getBytes() ); 
    connection.setRequestProperty("Authorization", "Basic " + encodedAuthorization); 
    //set various properties by using reference of connection according to your requirement
   } 
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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