Nikos Maravitsas

About Nikos Maravitsas

Nikos has graduated from the Department of Informatics and Telecommunications of The National and Kapodistrian University of Athens. Currently, his main interests are system’s security, parallel systems, artificial intelligence, operating systems, system programming, telecommunications, web applications, human – machine interaction and mobile development.

Application Authentication With JAX-WS

In this example we are going to see how to implement a simple application level authentication in JAX-WS. The notion of authentication is very well covered and its necessity is quite clear. In our tutorial we are going to authenticate a client to the endpoint server.

The idea is straight forward. The client who wants to consume the Web Service, will have to add and HTTP Request Header containing his username and password. The server then gets these headers and validates the client’s credentials. Of course, passwords should be encrypted (not only hashed). In fact, all the communication should be encrypted to achieve an acceptable level of security. But in this tutorial we are going to keep things as simple as possible, but you should keep in mind that authentication along with session management are hard and crucial issues when developing a secure Web application.

The code of this tutorial is going to be based in JAX-WS Hello World Example – RPC Style.

1. Service Endpoint

In order to create our Web Service Endpoint:

  • First you have to create a Web Service Endpoint Interface. This interface will contain the declerations of all the methods you want to include in the Web Service.
  • Then you have to create a class that actually implements the above interface, which will be your Endpoint implementation.

Web Service Endpoint Interface (SEI)

The Web Service Endpoint Interface is similar to the perivous JAX-WS we’ve seen.

WebServiceInterface.java:

package com.javacodegeeks.enterprise.ws;

import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;

@WebService
@SOAPBinding(style = Style.RPC)
public interface WebServiceInterface{

	@WebMethod String getHelloWorldAsString(String name);

}

Web Service Endpoint Implementation

As we said in the introduction, the server would have to read the HTTP request headers that the client put, and validate its credetials. To access the context objects of the message, our Service Endpoint Implementation has to obtain a MessageContext object through a WebServiceContext. The WebServiceContext interface enables a web service endpoint implementation class to access message contexts and security information of  the requester. The service runtime will inject the WebServiceContext on any field marked with @Resource annotation. To get a MessageContext instance, we can call the WebServiceContext‘s getMessageContext() method.

The HTTP Request Header will be retrieved using MessageContext's get method with MessageContext.HTTP_REQUEST_HEADERS as a parameter which nominates the kind of context we want from the message. The Header will be retrieved as a Map which is very convenient because you can specify (key,value) pairs directy. Thus, we retrieve the corespoding credentials.

WebServiceImpl.java:

package com.javacodegeeks.enterprise.ws;

import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.jws.WebService;
import javax.xml.ws.WebServiceContext;
import javax.xml.ws.handler.MessageContext;

@WebService(endpointInterface = "com.javacodegeeks.enterprise.ws.WebServiceInterface")
public class WebServiceImpl implements WebServiceInterface {

	@Resource
	WebServiceContext webServiceContext;

	@Override
	public String getHelloWorldAsString(String str) {

		MessageContext messageContext = webServiceContext.getMessageContext();

		// get request headers
		Map<?,?> requestHeaders = (Map<?,?>) messageContext.get(MessageContext.HTTP_REQUEST_HEADERS);
		List<?> usernameList = (List<?>) requestHeaders.get("username");
		List<?> passwordList = (List<?>) requestHeaders.get("password");

		String username = "";
		String password = "";

		if (usernameList != null) {
			username = usernameList.get(0).toString();
		}

		if (passwordList != null) {
			password = passwordList.get(0).toString();
		}

                // of course this is not real validation
                // you should validate your users from stored databases credentials
		if (username.equals("nikos") && password.equals("superpassword")) {

			return "Valid User :"+str;

		} else {

			return "Unknown User!";
		}
	}
}

Web Service Endpoint Publisher

WebServicePublisher.java:

package com.javacodegeeks.enterprise.ws;

import javax.xml.ws.Endpoint;
import com.javacodegeeks.enterprise.ws.WebServiceImpl;

public class WebServicePublisher{

	public static void main(String[] args) {
	   Endpoint.publish("http://localhost:8888/webservice/helloworld", new WebServiceImpl());
    }
}

Now when you run the publisher the Web Service will be available to the clients, deployed in the URL:

http://localhost:8888/webservice/helloworld

And this is the wsdl file that is automatically created (published in http://localhost:8888/webservice/helloworld?wsdl):

WSDL:

<?xml version="1.0" encoding="UTF-8"?>

<!-- Published by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is 
	JAX-WS RI 2.2.4-b01. -->

<!-- Generated by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is 
	JAX-WS RI 2.2.4-b01. -->
-
<definitions name="WebServiceImplService" targetNamespace="http://ws.enterprise.javacodegeeks.com/"
	xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
	xmlns:tns="http://ws.enterprise.javacodegeeks.com/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
	xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata"
	xmlns:wsp1_2="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsp="http://www.w3.org/ns/ws-policy"
	xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
	<types />
	-
	<message name="getHelloWorldAsString">
		<part name="arg0" type="xsd:string" />
	</message>
	-
	<message name="getHelloWorldAsStringResponse">
		<part name="return" type="xsd:string" />
	</message>
	-
	<portType name="WebServiceInterface">
		-
		<operation name="getHelloWorldAsString">
			<input message="tns:getHelloWorldAsString"
				wsam:Action="http://ws.enterprise.javacodegeeks.com/WebServiceInterface/getHelloWorldAsStringRequest" />
			<output message="tns:getHelloWorldAsStringResponse"
				wsam:Action="http://ws.enterprise.javacodegeeks.com/WebServiceInterface/getHelloWorldAsStringResponse" />
		</operation>
	</portType>
	-
	<binding name="WebServiceImplPortBinding" type="tns:WebServiceInterface">
		<soap:binding style="rpc"
			transport="http://schemas.xmlsoap.org/soap/http" />
		-
		<operation name="getHelloWorldAsString">
			<soap:operation soapAction="" />
			-
			<input>
				<soap:body namespace="http://ws.enterprise.javacodegeeks.com/"
					use="literal" />
			</input>
			-
			<output>
				<soap:body namespace="http://ws.enterprise.javacodegeeks.com/"
					use="literal" />
			</output>
		</operation>
	</binding>
	-
	<service name="WebServiceImplService">
		-
		<port name="WebServiceImplPort" binding="tns:WebServiceImplPortBinding">
			<soap:address location="http://localhost:8888/webservice/helloworld" />
		</port>
	</service>
</definitions>

2. Java Web Service Client

On the other side, the client has to make a new HTTP Request Header containing his credentials and add it to the SOAP message. To access and manupulate the request contexts of the message the client has to get a BindingProvider from the service port and use getRequestContext() method. The BindingProvider interface enables the client to access and manipulate the associated context objects for request and response messages. The Request Context is retrieved as a Map object. We then, need to add two properties to that object. MessageContext.ENDPOINT_ADDRESS_PROPERTY to nominate the target service endpoint address. Next, we simply create a Map containing our credentials. To add this object as a header we use MessageContext.HTTP_REQUEST_HEADERS argument.

WebServiceClient.java:

package com.javacodegeeks.enterprise.ws.client;

import java.net.URL;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.namespace.QName;
import javax.xml.ws.BindingProvider;
import javax.xml.ws.Service;
import javax.xml.ws.handler.MessageContext;
import com.javacodegeeks.enterprise.ws.WebServiceInterface;

public class WebServiceClient{

	public static void main(String[] args) throws Exception {

	    URL wsdlUrl = new URL("http://localhost:8888/webservice/helloworld?wsdl");

	    //qualifier name ...
        QName qname = new QName("http://ws.enterprise.javacodegeeks.com/", "WebServiceImplService");

        Service service = Service.create(wsdlUrl, qname);

        WebServiceInterface sayHello = service.getPort(WebServiceInterface.class);

        Map<String, Object> requestContext = ((BindingProvider)sayHello).getRequestContext();

        requestContext.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, "http://localhost:8888/webservice/helloworld?wsdl");

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

        requestHeaders.put("username", Collections.singletonList("nikos"));
        requestHeaders.put("Password", Collections.singletonList("superpassword"));

        requestContext.put(MessageContext.HTTP_REQUEST_HEADERS, requestHeaders);

        System.out.println(sayHello.getHelloWorldAsString("- This is Java Code Geeks"));

    }
}

The output of the above program will be:

Valid User :- This is Java Code Geeks

SOAP Trafic

Now you can take a look at the SOAP envelops so see the added HTTP Request Header.

Client Request:

GET /webservice/helloworld?wsdl HTTP/1.1
User-Agent: Java/1.7.0_17
Host:
localhost:9999
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*;
q=.2
Connection: keep-alive

POST /webservice/helloworld?wsdl HTTP/1.1
Accept: text/xml, multipart/related
Content-Type: text/xml; charset=utf-8
Password: superpassword
SOAPAction: "http://ws.enterprise.javacodegeeks.com/WebServiceInterface/getHelloWorldAsStringRequest"
User-Agent: JAX-WS RI 2.2.4-b01
username: nikos
Host: localhost:9999
Connection: keep-alive
Content-Length: 261

<?xml version="1.0" ?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
	<S:Body>
		<ns2:getHelloWorldAsString xmlns:ns2="http://ws.enterprise.javacodegeeks.com/">
			<arg0>- This is Java Code Geeks</arg0>
		</ns2:getHelloWorldAsString>
	</S:Body>
</S:Envelope>

Server Response:

HTTP/1.1 200 OK
Transfer-encoding: chunked
Content-type:
text/xml;charset=utf-8
Date: Wed, 11 Sep 2013 14:21:03 GMT

860
<?xml version="1.0" encoding="UTF-8"?><!-- 
	Published by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS 
	RI 2.2.4-b01. --><!-- 
	Generated by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS 
	RI 2.2.4-b01. -->
<definitions
	xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
	xmlns:wsp="http://www.w3.org/ns/ws-policy" xmlns:wsp1_2="http://schemas.xmlsoap.org/ws/2004/09/policy"
	xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
	xmlns:tns="http://ws.enterprise.javacodegeeks.com/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
	xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://ws.enterprise.javacodegeeks.com/"
	name="WebServiceImplService">
	<types></types>
	<message name="getHelloWorldAsString">
		<part name="arg0" type="xsd:string"></part>
	</message>
	<message name="getHelloWorldAsStringResponse">
		<part name="return" type="xsd:string"></part>
	</message>
	<portType name="WebServiceInterface">
		<operation name="getHelloWorldAsString">
			<input
				wsam:Action="http://ws.enterprise.javacodegeeks.com/WebServiceInterface/getHelloWorldAsStringRequest"
				message="tns:getHelloWorldAsString"></input>
			<output
				wsam:Action="http://ws.enterprise.javacodegeeks.com/WebServiceInterface/getHelloWorldAsStringResponse"
				message="tns:getHelloWorldAsStringResponse"></output>
		</operation>
	</portType>
	<binding name="WebServiceImplPortBinding" type="tns:WebServiceInterface">
		<soap:binding transport="http://schemas.xmlsoap.org/soap/http"
			style="rpc"></soap:binding>
		<operation name="getHelloWorldAsString">
			<soap:operation soapAction=""></soap:operation>
			<input>
				<soap:body use="literal" namespace="http://ws.enterprise.javacodegeeks.com/"></soap:body>
			</input>
			<output>
				<soap:body use="literal" namespace="http://ws.enterprise.javacodegeeks.com/"></soap:body>
			</output>
		</operation>
	</binding>
	<service name="WebServiceImplService">
		<port name="WebServiceImplPort" binding="tns:WebServiceImplPortBinding">
			<soap:address location="http://localhost:9999/webservice/helloworld"></soap:address>
		</port>
	</service>
</definitions>
0

HTTP/1.1 200 OK
Transfer-encoding: chunked
Content-type: text/xml;
charset=utf-8
Date: Wed, 11 Sep 2013 14:21:03 GMT

5e
<?xml version="1.0" ?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
	<S:Body>
		c7
		<ns2:getHelloWorldAsStringResponse
			xmlns:ns2="http://ws.enterprise.javacodegeeks.com/">
			<return>Valid User :- This is Java Code Geeks</return>
		</ns2:getHelloWorldAsStringResponse>
	</S:Body>
</S:Envelope>
0

This was an example on Application Authentication With JAX-WS. Donwload the Eclipse project of this example : JAX-WS-AUTH.zip

Related Whitepaper:

Java Essential Training

Author David Gassner explores Java SE (Standard Edition), the language used to build mobile apps for Android devices, enterprise server applications, and more!

The course demonstrates how to install both Java and the Eclipse IDE and dives into the particulars of programming. The course also explains the fundamentals of Java, from creating simple variables, assigning values, and declaring methods to working with strings, arrays, and subclasses; reading and writing to text files; and implementing object oriented programming concepts. Exercise files are included with the course.

Get it Now!  

Examples Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use
All trademarks and registered trademarks appearing on Examples Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Examples Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.

Sign up for our Newsletter

15,153 insiders are already enjoying weekly updates and complimentary whitepapers! Join them now to gain exclusive access to the latest news in the Java world, as well as insights about Android, Scala, Groovy and other related technologies.

As an extra bonus, by joining you will get our brand new e-books, published by Java Code Geeks and their JCG partners for your reading pleasure! Enter your info and stay on top of things,

  • Fresh trends
  • Cases and examples
  • Research and insights
  • Two complimentary e-books