[java] Java Web Service client basic authentication

I have created a JAX-WS Web Service on top of Glassfish which requires basic HTTP authentication.

Now I want to create a standalone java application client for that Web Service but I don't have a clue of how to pass the username and password.

It works with Eclipse's Web Service explorer, and examining the wire I found this:

POST /SnaProvisioning/SnaProvisioningV1_0 HTTP/1.1
Host: localhost:8080
Content-Type: text/xml; charset=utf-8
Content-Length: 311
Accept: application/soap+xml, application/dime, multipart/related, text/*
User-Agent: IBM Web Services Explorer
Cache-Control: no-cache
Pragma: no-cache
SOAPAction: ""
Authorization: Basic Z2VybWFuOmdlcm1hbg==
Connection: close

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:q0="http://ngin.ericsson.com/sna/types/v1.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <soapenv:Body>
    <q0:listServiceScripts/>
  </soapenv:Body>
</soapenv:Envelope>

How do I pass the username and password in this "Authorization" header using java code? Is it hashed or something like that? What is the algorithm?

Without security involved I have a working standalone java client:

SnaProvisioning myPort = new SnaProvisioning_Service().getSnaProvisioningV10Port();
myPort.listServiceScripts();

This question is related to java web-services jakarta-ee jax-ws

The answer is


If you are using a JAX-WS implementation for your client, such as Metro Web Services, the following code shows how to pass username and password in the HTTP headers:

 MyService port = new MyService();
 MyServiceWS service = port.getMyServicePort();

 Map<String, List<String>> credentials = new HashMap<String,List<String>>();

 credentials.put("username", Collections.singletonList("username"));
 credentials.put("password", Collections.singletonList("password"));

 ((BindingProvider)service).getRequestContext().put(MessageContext.HTTP_REQUEST_HEADERS, credentials);

Then subsequent calls to the service will be authenticated. Beware that the password is only encoded using Base64, so I encourage you to use other additional mechanism like client certificates to increase security.


If you use JAX-WS, the following works for me:

    //Get Web service Port
    WSTestService wsService = new WSTestService();
    WSTest wsPort = wsService.getWSTestPort();

    // Add username and password for Basic Authentication
    Map<String, Object> reqContext = ((BindingProvider) 
         wsPort).getRequestContext();
    reqContext.put(BindingProvider.USERNAME_PROPERTY, "username");
        reqContext.put(BindingProvider.PASSWORD_PROPERTY, "password");

This worked for me:

 BindingProvider bp = (BindingProvider) port;
 Map<String, Object> map = bp.getRequestContext();
 map.put(BindingProvider.USERNAME_PROPERTY, "aspbbo");
 map.put(BindingProvider.PASSWORD_PROPERTY, "9FFFN6P");

Some context additional about basic authentication, it consists in a header which contains the key/value pair:

Authorization: Basic Z2VybWFuOmdlcm1hbg==

where "Authorization" is the headers key, and the headers value has a string ( "Basic" word plus blank space) concatenated to "Z2VybWFuOmdlcm1hbg==", which are the user and password in base 64 joint by double dot

String name = "username";
String password = "secret";
String authString = name + ":" + password;
String authStringEnc = new BASE64Encoder().encode(authString.getBytes());
...
objectXXX.header("Authorization", "Basic " + authStringEnc);

The easiest option to get this working is to include Username and Password under of request. See sample below.

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:typ="http://xml.demo.com/types" xmlns:ser="http://xml.demo.com/location/services"
    xmlns:typ1="http://xml.demo.com/location/types">
    <soapenv:Header>
        <typ:requestHeader>
            <typ:timestamp>?</typ:timestamp>
            <typ:sourceSystemId>TEST</typ:sourceSystemId>
            <!--Optional: -->
            <typ:sourceSystemUserId>1</typ:sourceSystemUserId>
            <typ:sourceServerId>1</typ:sourceServerId>
            <typ:trackingId>HYD-12345</typ:trackingId>
        </typ:requestHeader>

        <wsse:Security soapenv:mustUnderstand="1"
            xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
            <wsse:UsernameToken wsu:Id="UsernameToken-emmprepaid"
                xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
                <wsse:Username>your-username</wsse:Username>
                <wsse:Password
                    Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">your-password</wsse:Password>
            </wsse:UsernameToken>
        </wsse:Security>
    </soapenv:Header>
    <soapenv:Body>
        <ser:getLocation>
            <!--Optional: -->
            <ser:GetLocation>
                <typ1:locationID>HYD-GoldenTulipsEstates</typ1:locationID>
            </ser:GetLocation>
        </ser:getLocation>
    </soapenv:Body>
</soapenv:Envelope>

The JAX-WS way for basic authentication is

Service s = new Service();
Port port = s.getPort();

BindingProvider prov = (BindingProvider)port;
prov.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, "myusername");
prov.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, "mypassword");

port.call();

for Axis2 client this may be helpful

...
serviceStub = new TestBeanServiceStub("<WEB SERVICE URL>"); // Set your value
HttpTransportProperties.Authenticator basicAuthenticator = new HttpTransportProperties.Authenticator();
List<String> authSchemes = new ArrayList<String>();
authSchemes.add(Authenticator.BASIC);
basicAuthenticator.setAuthSchemes(authSchemes); 
basicAuthenticator.setUsername("<UserName>"); // Set your value
basicAuthenticator.setPassword("<Password>"); // Set your value
basicAuthenticator.setPreemptiveAuthentication(true);
serviceStub._getServiceClient().getOptions().setProperty(org.apache.axis2.transport.http.HTTPConstants.AUTHENTICATE, basicAuthenticator);
serviceStub._getServiceClient().getOptions().setProperty(org.apache.axis2.transport.http.HTTPConstants.CHUNKED, "false");
...

To make your life simpler, you may want to consider using JAX-WS framework such as Apache CXF or Apache Axis2.

Here is the link that describes how to setup WS-Security for Apache CXF -> http://cxf.apache.org/docs/ws-security.html

EDIT By the way, the Authorization field just uses simple Base64 encoding. According to this ( http://www.motobit.com/util/base64-decoder-encoder.asp ), the decoded value is german:german.


Examples related to java

Under what circumstances can I call findViewById with an Options Menu / Action Bar item? How much should a function trust another function How to implement a simple scenario the OO way Two constructors How do I get some variable from another class in Java? this in equals method How to split a string in two and store it in a field How to do perspective fixing? String index out of range: 4 My eclipse won't open, i download the bundle pack it keeps saying error log

Examples related to web-services

How do I POST XML data to a webservice with Postman? How to send json data in POST request using C# org.springframework.web.client.HttpClientErrorException: 400 Bad Request How to call a REST web service API from JavaScript? The request was rejected because no multipart boundary was found in springboot Generating Request/Response XML from a WSDL How to send a POST request using volley with string body? How to send post request to the below post method using postman rest client How to pass a JSON array as a parameter in URL Postman Chrome: What is the difference between form-data, x-www-form-urlencoded and raw

Examples related to jakarta-ee

Java 11 package javax.xml.bind does not exist javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure The type java.io.ObjectInputStream cannot be resolved. It is indirectly referenced from required .class files Deploying Maven project throws java.util.zip.ZipException: invalid LOC header (bad signature) web.xml is missing and <failOnMissingWebXml> is set to true WELD-001408: Unsatisfied dependencies for type Customer with qualifiers @Default Name [jdbc/mydb] is not bound in this Context An internal error occurred during: "Updating Maven Project". java.lang.NullPointerException How to consume a SOAP web service in Java java.lang.ClassNotFoundException: com.sun.jersey.spi.container.servlet.ServletContainer

Examples related to jax-ws

What is the difference between JAX-RS and JAX-WS? How to do a SOAP Web Service call from Java class? How to programmatically set the SSLContext of a JAX-WS client? What is the difference between Document style and RPC style communication? Java Web Service client basic authentication How to add soap header in java JAX-WS client : what's the correct path to access the local WSDL? Java Webservice Client (Best way) How to change webservice url endpoint? JAX-WS - Adding SOAP Headers