Container Authentication with JAX-WS – (Tomcat version)

In this article, we show you how to implement container authentication with JAX-WS, under Tomcat 6.0. In this way, the authentication is declarative rather than programmatic like this – application authentication in JAX-WS. And Tomcat implement the container authentication via security realm.

At the end of this article, the deployed web service will authenticate user based on the authentication data stored in Tomcat’s conf/tomcat-users.xml file.

1. WebService

Create a simple JAX-WS, RPC style.

File : UserProfile.java


package com.mkyong.ws;

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

//Service Endpoint Interface
@WebService
@SOAPBinding(style = Style.RPC)
public interface UserProfile{
	
	@WebMethod
	String getUserName();
	
}

File : UserProfileImpl.java


package com.mkyong.ws;

import javax.jws.WebService;

//Service Implementation Bean
@WebService(endpointInterface = "com.mkyong.ws.UserProfile")
public class UserProfileImpl implements UserProfile{

	@Override
	public String getUserName() {
		
		return "getUserName() : returned value";
		
	}

}

2. web.xml

Configure a security role “operator”, make url “/user” required basic http authentication. See below web.xml file, self-explanatory.

File : web.xml


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, 
Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>
    //...
    <security-role>
     	<description>Normal operator user</description>
     	<role-name>operator</role-name>
   	</security-role>

	<security-constraint>
      	<web-resource-collection>
        	<web-resource-name>Operator Roles Security</web-resource-name>
        	<url-pattern>/user</url-pattern>
      	</web-resource-collection>

      	<auth-constraint>
        	<role-name>operator</role-name>
      	</auth-constraint>
      	<user-data-constraint>
          	<transport-guarantee>NONE</transport-guarantee>
      	</user-data-constraint>
   	</security-constraint>

	<login-config>
      	<auth-method>BASIC</auth-method>
   	</login-config>

    <servlet-mapping>
        <servlet-name>user</servlet-name>
        <url-pattern>/user</url-pattern>
    </servlet-mapping>
    //...
</web-app>
Note
In production, it’s recommended to set the transport guarantee to “CONFIDENTIAL“, so that any access to resources via normal http request, such as http://localhost:8080/ws/user, Tomcat will redirect the request to https request https://localhost:8443/ws/user. Of course, the redirect https can be configure in The Tomcat’s conf/server.xml.


<user-data-constraint>
    <transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>

See this article – Make Tomcat to support SSL or https connection

3. Tomcat Users

Add new role, username and password in $Tomcat/conf/tomcat-users.xml file. In this case, add new user “mkyong”,”123456″ and attached it to a role named “operator”.

File : $Tomcat/conf/tomcat-users.xml


<?xml version='1.0' encoding='utf-8'?>
<tomcat-users>
  <role rolename="tomcat"/>
  <role rolename="operator"/>
  <user username="tomcat" password="tomcat" roles="tomcat"/>
  <user username="mkyong" password="123456" roles="operator"/>
  <user name="admin" password="admin" roles="admin,manager" />
</tomcat-users>

4. Tomcat Realm

Configure security realm in $Tomcat/conf/server.xml file. In this case, uses default UserDatabaseRealm to read the authentication information in $Tomcat/conf/tomcat-users.xml.

File : $Tomcat/conf/server.xml


  <GlobalNamingResources>

    <Resource name="UserDatabase" auth="Container"
              type="org.apache.catalina.UserDatabase"
              description="User database that can be updated and saved"
              factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
              pathname="conf/tomcat-users.xml" />
  </GlobalNamingResources>
  
  <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
             resourceName="UserDatabase"/>

5. Deploy JAX-WS web service on Tomcat

See this detail guide on how to deploy JAX-WS web services on Tomcat.

6. Testing

Now, any access to your deployed web service is required username and password authentication, see figure :
URL : http://localhost:8080/WebServiceExample/user

jaxws-container-authentication--example

7. WebService Client

To access the deployed web service, bind a correct username and password like this :


    UserProfile port = service.getPort(UserProfile.class);
    BindingProvider bp = (BindingProvider) port;
    bp.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, "mkyong");
    bp.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, "123456");

File : WsClient.java


package com.mkyong.client;

import java.net.URL;
import javax.xml.namespace.QName;
import javax.xml.ws.BindingProvider;
import javax.xml.ws.Service;

import com.mkyong.ws.UserProfile;

public class WsClient{

        //can't parse wsdl "http://localhost:8080/WebServiceExample/user.wsdl" directly
	//save it as local file, and parse it
	private static final String WS_URL = "file:c://user.wsdl";
		
	public static void main(String[] args) throws Exception {
	   
	URL url = new URL(WS_URL);
        QName qname = new QName("http://ws.mkyong.com/", "UserProfileImplService");

        Service service = Service.create(url, qname);
        UserProfile port = service.getPort(UserProfile.class);
        
        //add username and password for container authentication
        BindingProvider bp = (BindingProvider) port;
        bp.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, "mkyong");
        bp.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, "123456");

        System.out.println(port.getUserName());
       
    }

}

output


getUserName() : returned value
Note
For those clients provided an invalid username or password, Tomcat will return following exception :


Exception in thread "main" com.sun.xml.internal.ws.client.ClientTransportException: 
	request requires HTTP authentication: Unauthorized

Done.

Download Source Code

Reference

  1. Tomcat realm HOW TO
  2. Example: Basic Authentication with JAX-WS
  3. SSL and HTTP BASIC authentication with Glassfish and JAX-WS

About the Author

author image
mkyong
Founder of Mkyong.com, love Java and open source stuff. Follow him on Twitter, or befriend him on Facebook or Google Plus. If you like my tutorials, consider make a donation to these charities.

Comments

Leave a Reply

avatar
newest oldest most voted
Evgen
Guest
Evgen

Can you explaine about “file:c://user.wsdl”?

neha agrawal
Guest
neha agrawal

Thanks for your tutorials!! I have learnt a lot about web service security from your site. Recently I read a lot web service security using OAuth. But couldn’t find any examples which can guide step by step through the process. Would you like to share your knowledge on this?

Evgen
Guest
Evgen

How implemented authentification with DB+JAX-WS?

Oussama
Guest
Oussama

hi mykyong,
this tutorial was amazing thank you.

RatMaster
Guest
RatMaster

You’re a rat…

Jenusin1239
Guest
Jenusin1239

confirmed by WHO(
World Health Organization)
Our Grand rat lord. Mykong.

hanane
Guest
hanane

i did exactely what is in the tutorial but my service does not accept my user name and password , can you help me plz ?

hanane
Guest
hanane

HI , i just fix it , i should modify tomcat-users.xml from the location ~/MyWorkspace/Servers/Tomcat v6.0 not in the installation file in my machine , that’s for help to others tnx

Jaskirat Singh Bamrah
Guest
Jaskirat Singh Bamrah
the authentication window does not accept my user name and password and it is in the tomcat-user.xml..... I have used axis2 and tomcat...

and a warning is there basic authentication without secure connection
Jaskirat Singh Bamrah
Guest
Jaskirat Singh Bamrah

hello mkyong….I create a web service using tomcat and axis2 in windows using eclipse
and when I update the web.xml as u mentioned above….even the tomcat-user.xml from program file.
I didnt made any change in service.xml

but when I run the service it does not accept my user name and password..directly from authentication required window…
Is is possible to access from there…or need to make a client….?

hanane
Guest
hanane

HI Jaskirat i have the same trouble , my service does not accept my user name and password , did you fix this? can youn help me plz ?

hanane
Guest
hanane

HI , i just fix it , i should modify tomcat-users.xml from the location ~/MyWorkspace/Servers/Tomcat v6.0 not in the installation file in my machine , that’s for help to others tnx

Vijayendra Bhati
Guest
Vijayendra Bhati
Hi, I am not sure why in my case following code is not working. // BindingProvider bp = (BindingProvider) pm; // bp.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, "vijay"); // bp.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, "vijay123"); So I googled a bit and added these lines Authenticator.setDefault(new Authenticator() { @Override protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication("vijay", "vijay123".toCharArray()); } }); Any reason ? Is I am missing something here why original code was giving HTTP ERROR 401 to me.I know its related to authentication.But why ? Is there are any side effects of using Authenticator ? public static void main(String[] args) throws Exception{ // TODO Auto-generated method stub /*********** WORKING *****/… Read more »
Nikhil
Guest
Nikhil
Hi MKyong I think I have been succesfully been able to deploy your example to tomcat. But when I try to run WsClient.java as a java application it says that it cannot access that it cannot access http://localhost:8080/WebServicesExample/user?wsdl and I understand why that is because I do have a user.wsdl file defined on my hard-drive. Even when I try to access the WSDL file from http://localhost:8080/WebServicesExample/user it gives me a 404 Not Found type of error message. So am I expected to create my own WSDL file for this or get the WSDL file from somewhere else ? Was that… Read more »
Jone Swantko
Guest
Jone Swantko

I can see which you are putting a a lot of efforts into your blog. Preserve posting the good perform.Some really helpful information in there. Bookmarked. Wonderful to see your website. Thanks!

trackback
JAX-WS Tutorial

[…] a detail example to show you how to handle application level authentication with JAX-WS.Container Authentication with JAX-WS + (Tomcat version) Here’s a detail example to show you how to implement container authentication with JAX-WS, […]

Henrik Winther Jensen
Guest
Henrik Winther Jensen

Just a thought:

Is there anyway to persuade tomcat to give out the wsdl, without requiring a userid/password?

Yes, I know its a far shot, since the authentication is bound to the service that must be protected. But maybe someone comes up with a solution anyway.

KR
Henrik

Henrik Winther Jensen
Guest
Henrik Winther Jensen

Am I the only one who thinks that getting the wsdl from a local file is pretty awful?
I if you deploy your client in a jar, you will need to put the wsdl somewhere in your filesystem, and if the wsdl changes, you are up the creek without a paddle.

But it seems that with jax-ws/Basic authentication this is the only option.

Anyone with a solution to this will get my personal commendation with oak leaves, eagles and diamonds!

Kind regards
Henrik

Rodrigo H.R
Guest
Rodrigo H.R

Hi, I were implementing your tutorial and it worked fine with one WS, however, when I wanted to assign to a user more than one WS I got troubles…I mean, for example, I have 4 WS and I want to grant permissions over 2 specified WS to 2 different users, when the user access to one of its suppossed assigned WS it works fine, but after the user can access the other WS. I don´t know if there is a concrete way to organize de web.xml. Thx for your attention. Hope your answer. =D

trackback
Container Authentication with JAX-WS – (Tomcat version)

[…] programmatic like this – application authentication in JAX-WS. And Tomcat implement the… [full post] mkyong Mkyong Dot Com jax-wstomcatweb services 0 0 0 0 […]