JAX-RS Security using Digest Authentication and Authorization

JAX-RS Security using Digest Authentication and Authorization

In this tutorial we will discuss how to secure JAX-RS RESTful web services using Digest Authentication. This form of access authentication is slightly more complex than the previously discussed JAX-RS Basic Authentication Tutorial. As you will see most of the configuration changes are virtually identical however, the communication mechanism between the server and the client are vastly different.

Advantages/Disadvantages of HTTP Digest Access Authentication

Advantages

  • The passwords are never transmitted during authentication between client and server
  • Since passwords are never transmitted, TLS/SSL is not required
  • The passwords are not used directly in the digest, but rather a digest is created by using a combination of (username:realm:password)
  • Newer versions contain nonce to prevent plaintext attacks with the use of rainbow tables which are used for reversing crytographic hash functions.
  • Nonce is allowed to contain timestamps to prevent replay attacks

Disadvantages

  • Slower than Basic Authentication as 2 calls are needed for every request
  • Digest access authentication is vulnerable to a man-in-the-middle attack
  • Digest access authentication was poorly implemented on some servers allowing passwords to be stored using reversible encryption instead of the recommended one way hashing MD5 algorithm.

Getting Started

In order to run this tutorial yourself, you will need the following:

  • Java JDK 1.6 or greater
  • Favorite IDE Spring Tool Suite (STS), Eclipse IDE or NetBeans (I happen to be using STS because it comes with a Tomcat server built-in)
  • Tomcat 7 or greater or other popular container (Weblogic, Websphere, Glassfish, JBoss, VMWare vFabric, etc). For this tutorial I am using VMware vFabric tc Server Developer Edition which is essentially an enhanced Tomcat instance integrated with Spring STS
  • Jersey JAX-RS
  • log4J (for logging purposes)

Required Libraries

Copy all of the following jars to WebContent->WEB-INF->lib folder.

 asm-3.1.jar
 jackson-core-asl-1.9.2.jar
 jackson-jaxrs-1.9.2.jar
 jackson-mapper-asl-1.9.2.jar
 jackson-xc-1.9.2.jar
 jersey-client-1.18.jar
 jersey-core-1.18.jar
 jersey-json-1.18.jar
 jersey-server-1.18.jar
 jersey-servlet-1.18.jar
 jettison-1.1.jar
 jsr311-api-1.1.1.jar
 log4j-1.2.17.jar

Complete Project Overview

I have added the project overview to give you a full view of the structure and show you all files contained in this sample project.

jax-rs_digest_security_proj

RESTful Web Service End Points

Restricted URIs will be shown with LOCK icon in the table below.

#URIMethodDescription
1/rest/customers/versionPOSTDisplays the current version of the API being used. Non-restricted REST end-point
2/rest/customers/listGETReturns all customers currently housed in our internal datastore as a JSON Array. Non-restricted REST end-point
3/rest/customers/get/{id}GETRetrieves the customer by ID returning the customer details as JSON object. Non-restricted REST end-point
4/rest/customers/search/{name}GETSearches for all customers by name returning the all customers that match the criteria as a JSON Array. Non-restricted REST end-point
5/rest/customers/secure/addPOSTAllows you to add customers to our internal datastore. Customer must be passed as JSON object. If the ID associated with the new customer does not exist, it will be added and the record will be returned to the user. Otherwise, an appropriate message will be logged and the existing customer will be returned to the user. **Restricted REST end-point
6/rest/customers/secure/updatePUTAllows you to update a customer in our internal datastore. Customer must be passed as JSON object. If the ID associated with the customer does not exist, error message will be logged, and it will fail and no record will be updated. Otherwise, customer with the customer ID will be updated. **Restricted REST end-point
7/rest/customers/secure/delete/{id}DELETEAllows you to delete a customer with that customer ID in our internal datastore. If the ID does not exist, error message will be logged, and it will fail and no record will be deleted. Otherwise, customer with the customer ID will be remove from our datastore. **Restricted REST end-point

Digest Authentication Communication Flow

digest_auth_flow

1 – Initial Request for Protected Resource

* About to connect() to localhost port 8888 (#0)
*   Trying 127.0.0.1... connected
* Connected to localhost (127.0.0.1) port 8888 (#0)
* Server auth using Digest with user 'user1'
> PUT /RestfulDigestSecurityExample/rest/customers/secure/update 
HTTP/1.1
> User-Agent: curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 
NSS/3.14.0.0 zlib/1.2.3 libidn/1.18 libssh2/1.4.2
> Host: localhost:8888
> Accept: */*
> Content-Type: application/json
> Content-Length: 0

2 – Challenge Response from Server

< HTTP/1.1 401 Unauthorized
< Server: Apache-Coyote/1.1
< Cache-Control: private
< Expires: Wed, 07 Feb 1969 19:00:00 EST
< WWW-Authenticate: Digest realm="UserDatabase", qop="auth", 
nonce="1449161851859:1132c63829013066e5d9e7cbd532a6dd", 
opaque="44426A180C3A3D7DBCC153ACDA7F5958"
< Content-Type: text/html;charset=utf-8
< Content-Language: en
< Content-Length: 994
< Date: Thu, 07 Feb 2015 16:57:31 GMT

3 – Client resends request with Authorization Header

* Ignoring the response-body
* Connection #0 to host localhost left intact
* Issue another request to this URL: 'http://localhost:8888
/RestfulDigestSecurityExample/rest/customers/secure/update'
* Re-using existing connection! (#0) with host localhost
* Connected to localhost (127.0.0.1) port 8888 (#0)
* Server auth using Digest with user 'user1'
> PUT /RestfulDigestSecurityExample/rest/customers/secure/update 
HTTP/1.1
> Authorization: Digest username="user1", realm="UserDatabase", 
nonce="1449161851859:1132c63829013066e5d9e7cbd532a6dd", 
uri="/RestfulDigestSecurityExample/rest/customers/secure/update", 
cnonce="MjU3NzEx", nc=00000001, qop="auth", 
response="3d3fc7ef13957ebba7e033a3b4b35a86", 
opaque="44426A180C3A3D7DBCC153ACDA7F5958"
> User-Agent: curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 
NSS/3.14.0.0 zlib/1.2.3 libidn/1.18 libssh2/1.4.2
> Host: localhost:8888
> Accept: */*
> Content-Type: application/json
> Content-Length: 122

4 – Server Responds with Success Code and Payload (on Success)

< HTTP/1.1 200 OK
< Server: Apache-Coyote/1.1
< Cache-Control: private
< Expires: Wed, 07 Feb 1969 19:00:00 EST
< Content-Type: application/json
< Transfer-Encoding: chunked
< Date: Thu, 07 Feb 2015 16:57:31 GMT
<
* Connection #0 to host localhost left intact
* Closing connection #0

{"id":102,"name":"Jermaine Z. Holston","address":
"17852 Cedar Lane","city":"Princeton","state":"New Jersey",
"zip":"08540"}

Configuring Application for Digest Authentication

In order to configure JAX-RS application security using Digest Authentication we need to do the following:

  • Enable HTTP Digest Authentication in our web.xml file
  • Add Security Constraints
  • Add Authorization Constraints
  • Add Login Configuration Element
  • Add Security Roles

Sample web.xml snippet

<!-- Add Security for RESTful Web Services Using Digest Authentication  -->
<security-constraint>
	<display-name>Secure REST Area</display-name>
	<web-resource-collection>
		<web-resource-name>Secure REST</web-resource-name>
		<url-pattern>/rest/customers/secure/*</url-pattern>
		<http-method>PUT</http-method>
		<http-method>POST</http-method>
		<http-method>DELETE</http-method>
	</web-resource-collection>

	<auth-constraint>
		<role-name>admin</role-name>
	</auth-constraint>
</security-constraint>

<login-config>
	<auth-method>DIGEST</auth-method>
	<realm-name>UserDatabase</realm-name>
</login-config>

<security-role>
	<role-name>admin</role-name>
</security-role>

Generating the One-way hash on Tomcat

You will need to run the digest command from the CATALINA_HOME/bin directory.
You will use the following format CATALINA_HOME/bin/digest -a {algorithm, where algorithm = MD5} {username:realm:password}

Using the DIGEST command for generating the one-way MD5 hash

digest -a MD5 user1:UserDatabase:password1

OUTPUT of Digest Command

Once this command completes, you will need to take the hash generated after the colon (:) and copy it to the password field in the Tomcat (tomcat-users.xml) configuration file (as seen below).

user1:UserDatabase:password1:737d2473cfd0f5d7f1cf5e94ffaebce9d569f83082fe60f892023915a361bb86$1$4bea76b7c02caf67eccc2db289c18e1f

Server-Side setup for Tomcat (tomcat-users.xml)

<?xml version='1.0' encoding='utf-8'?>

<tomcat-users xmlns="http://tomcat.apache.org/xml"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://tomcat.apache.org/xml tomcat-users.xsd"
              version="1.0">

  <role rolename="admin"/>
  <user username="user1" password="9e1094addb041288128736e388b25a4d9969077f2aa719e5bb9fb0a02ec9ac45$1$eea14d35d1e50edf36504dcd6f756c8b" roles="admin"/>

</tomcat-users>

XML Deployment Descriptor Definitions

  • Security Constraints – Used to define access permissions for a set of resources as defined by web resource collection. Web resource collections are defined by a URL patterns and HTTP Methods in order to protect a resource.
  • Authorization Constraints – Authorization Constraints indicate which users in the specified roles are permitted access to this particular resource collection.
  • Login Configuration – Login Configuration is used to specify the authentication method to be used for access to restricted resource and the Realm in which the user will be authenticated against.
  • Security Roles – A security role defines which role will be used for the permission to access a particular set of resources in an application.

The Model (Customer.java)

This will be used to as the object which we store and retrieve in order to test out our application. I added it because I wanted my web service to store and retrieve some Java object. For the sake of this tutorial it is really not that important.

package com.avaldes.model;

public class Customer {
  private int id;
  private String name;
  private String address;
  private String city;
  private String state;
  private String zip;

  public Customer(int id, 
          String name, 
          String address, 
          String city, 
          String state, 
          String zip) {
    
    super();
    this.id = id;
    this.name = name;
    this.address = address;
    this.city = city;
    this.state = state;
    this.zip = zip;
  }

  public Customer() {
  }
  
  public int getId() {
    return id;
  }

  public void setId(int id) {
    this.id = id;
  }

  public String getName() {
    return name;
  }
  
  public void setName(String name) {
    this.name = name;
  }
  
  public String getAddress() {
    return address;
  }
  
  public void setAddress(String address) {
    this.address = address;
  }
  
  public String getCity() {
    return city;
  }
  
  public void setCity(String city) {
    this.city = city;
  }
  
  public String getState() {
    return state;
  }
  
  public void setState(String state) {
    this.state = state;
  }
  
  public String getZip() {
    return zip;
  }
    
  public void setZip(String zip) {
    this.zip = zip;
  }
  
  @Override
  public String toString() {
    return "Customer [id=" + id + ", name=" + name 
        + ", address=" + address + ", city=" 
        + city + ", state=" + state
        + ", zip=" + zip + "]";
  }
}

Complete Program (RestfulSecurityExample.java)

package com.avaldes.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import org.apache.log4j.Logger;

import com.avaldes.model.Customer;

@Path("/customers")
public class RestfulSecurityExample {
  static Logger logger = Logger.getLogger(RestfulSecurityExample.class);
  static String xmlString = null;
  static final String api_version = "1.01.0001A";
  static Map<Integer, Customer> customers = new HashMap<Integer, Customer>();
  
  static {
    logger.info("Initializing Internal DataStore...");
    customers.put(101, new Customer(101, "Alex Jackson", 
						"100 Main Street", "Paterson", "New Jersey", "07501"));
    customers.put(102, new Customer(102, "Jermaine Holston", 
						"52 Cedar Lane", "Princeton", "New Jersey", "08540"));
    customers.put(103, new Customer(103, "Andre Garcia", 
						"76 Florence Drive", "Newark", "New Jersey", "07102"));
    customers.put(104, new Customer(104, "Lisa Roman", 
						"1033 Clare Street", "Bridgewater", "New Jersey", "08807"));
  }
    
  @Path("/version")
  @GET
  @Produces(MediaType.TEXT_HTML)
  public String returnVersion() {
    return "<p>Version: " + api_version + "</p>";
  }

  @Path("/list")
  @GET
  @Produces(MediaType.APPLICATION_JSON)
  public ArrayList<Customer> getAllCustomer() {
    
    logger.info("Getting all Customers...");
    ArrayList<Customer> customerList 
		   = new ArrayList<Customer>(customers.values());
    return customerList;
  }
  
  @Path("/get/{id}")
  @GET
  @Produces(MediaType.APPLICATION_JSON)
  public Customer getCustomerById(@PathParam("id") Integer id) {
    logger.info("Getting Customer by ID: " + id);

    Customer customer = customers.get(id);
    if (customer != null) {
      logger.info("Inside getCustomerById, returned: " 
			                                     + customer.toString());
    } else {
      logger.info("Inside getCustomerById, ID: " + id + ", NOT FOUND!");
    }
    return customer;
  }
  
  @Path("/search/{name}")
  @GET
  @Produces(MediaType.APPLICATION_JSON)
  public ArrayList<Customer> searchCustomerByName(
	                               @PathParam("name") String name) {
																 
    logger.info("Searching customer by Name: " + name);
    
    ArrayList<Customer> customerList = new ArrayList<Customer>();   
    for (Customer c: customers.values()) {
      if (c.getName().toUpperCase().contains(name.toUpperCase()))
        customerList.add(c);
    }
    return customerList;
  }
  
  // ---[ Add Protected URIs below as defined in web.xml ]--- 
  @Path("/secure/update")
  @PUT
  @Consumes(MediaType.APPLICATION_JSON)
  @Produces(MediaType.APPLICATION_JSON)
  public Customer updateCustomer(Customer customer) {
    if (customers.containsKey(customer.getId())) {
      customers.put(customer.getId(), customer);
      logger.info("updateCustomer with ID: " + customer.getId());
      logger.info("Inside updateCustomer, returned: " 
			                                 + customer.toString());
    } else {
      logger.error("Customer with ID: " 
			   + customer.getId() + ", does NOT exist...");
      return null;
    }
    return customer; 
  }
  
  @Path("/secure/add")
  @POST
  @Consumes(MediaType.APPLICATION_JSON)
  @Produces(MediaType.APPLICATION_JSON)
  public Customer addCustomer(Customer customer) {
    logger.info("Adding customer with ID: " + customer.getId());
    
    if (!customers.containsKey(customer.getId())) {
      logger.info("Inside addCustomer, returned: " + customer.toString());
      customers.put(customer.getId(), customer);
      logger.info("# of customer: " + customers.size());
      logger.info("customer are now: " + customers); 
    } else {
      logger.error("Customer with ID: " + customer.getId() + ", exists...");
      Customer cust = customers.get(customer.getId());
      logger.info("Customer: " + cust);
      return cust;
    }
    
    return customer;
  }
  
  @Path("/secure/delete/{id}")
  @DELETE
  @Produces(MediaType.APPLICATION_JSON)
  public Customer deleteCustomerById(@PathParam("id") Integer id) {
    System.out.println("Deleting actor with ID: " + id);
    
    Customer customer = customers.remove(id);
    if (customer != null) {
      logger.info("Inside deleteCustomerById, returned: " 
			                                         + customer.toString());
    } else {
      logger.error("Inside deleteCustomerById, ID: " + id 
			                                             + ", NOT FOUND!");
    }
    return customer;
  }
}

LOG4J Configuration File (log4j.xml)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration PUBLIC "
          -//APACHE//DTD LOG4J 1.2//EN" "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">

  <!-- Appenders -->
  <appender name="console" class="org.apache.log4j.ConsoleAppender">
  <param name="Target" value="System.out" />
    <layout class="org.apache.log4j.PatternLayout">
    <param name="ConversionPattern" value="%-5p: %c - %m%n" />
    </layout>
  </appender>
  
  <!-- Application Loggers -->
  <logger name="com.avaldes">
    <level value="info" />
  </logger>

  <!-- Root Logger -->
  <root>
    <priority value="warn" />
    <appender-ref ref="console" />
  </root>
</log4j:configuration>

Web Deployment Descriptor (web.xml)

This is a pretty straight forward deployment descriptor file – only thing you need to add is the location of you java package in the Jersey ServletContainer entry as init-param. Please ensure you add it to the web.xml file as shown below.

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xmlns="http://java.sun.com/xml/ns/javaee" 
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
	http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" 
	id="WebApp_ID" version="3.0">
	
  <display-name>JAX-RS Secured Web Application</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
  
  <servlet>
    <servlet-name>Jersey REST Service</servlet-name>
    <servlet-class>
	com.sun.jersey.spi.container.servlet.ServletContainer
    </servlet-class>
    <init-param>
      <param-name>com.sun.jersey.config.property.packages</param-name>
      <param-value>com.avaldes</param-value>
    </init-param>
    <init-param>
      <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
      <param-value>true</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  
  <servlet-mapping>
    <servlet-name>Jersey REST Service</servlet-name>
    <url-pattern>/rest/*</url-pattern>
  </servlet-mapping>
  
  <!-- Add Security for RESTful Web Services Using Digest Authentication  -->
  <security-constraint>
    <display-name>Secure REST Area</display-name>
    <web-resource-collection>
      <web-resource-name>Secure REST</web-resource-name>
      <url-pattern>/rest/customers/secure/*</url-pattern>
      <http-method>PUT</http-method>
      <http-method>POST</http-method>
      <http-method>DELETE</http-method>
    </web-resource-collection>
  
    <auth-constraint>
      <role-name>admin</role-name>
    </auth-constraint>
  </security-constraint>

  <login-config>
    <auth-method>DIGEST</auth-method>
    <realm-name>UserDatabase</realm-name>
  </login-config>

  <security-role>
    <role-name>admin</role-name>
  </security-role>
    
</web-app>

Testing out the Web Services

To test out the application I used both CURL and Postman which is a Google Chrome Application. Using this tool I validated each of the REST API calls. Please review the screen shots below:

Using CURL to Test out the Digest Access Authentication

curl -H "Content-Type: application/json" -X PUT -d "{\"id\":102,
\"name\":\"Jermaine Z. Holston\",\"address\":\"17852 Cedar Lane\",
\"city\":\"Princeton\",\"state\":\"New Jersey\",\"zip\":\"08540\"}" 
-v --user user1:password1 --digest http://localhost:8888/
RestfulDigestSecurityExample/rest/customers/secure/update

Complete output of our Test

curl -H "Content-Type: application/json" -X PUT -d "{\"id\":102,\"name\":\"Jermaine Z. Holston\",\"address\":\"17852 Cedar Lane\",\"city\":\"Princeton\",\"state\":\"New Jersey\",\"zip\":\"08540\"}" -v --user user1:password1 --digest http://localhost:8888/RestfulDigestSecurityExample/rest/customers/secure/update

* About to connect() to localhost port 8888 (#0)
*   Trying 127.0.0.1... connected
* Connected to localhost (127.0.0.1) port 8888 (#0)
* Server auth using Digest with user 'user1'
> PUT /RestfulDigestSecurityExample/rest/customers/secure/update HTTP/1.1
> User-Agent: curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.14.0.0 zlib/1.2.3 libidn/1.18 libssh2/1.4.2
> Host: localhost:8888
> Accept: */*
> Content-Type: application/json
> Content-Length: 0
>
< HTTP/1.1 401 Unauthorized
< Server: Apache-Coyote/1.1
< Cache-Control: private
< Expires: Wed, 07 Feb 1969 19:00:00 EST
< WWW-Authenticate: Digest realm="UserDatabase", qop="auth", nonce="1449161851859:1132c63829013066e5d9e7cbd532a6dd", opaque="44426A180C3A3D7DBCC153ACDA7F5958"
< Content-Type: text/html;charset=utf-8
< Content-Language: en
< Content-Length: 994
< Date: Thu, 07 Feb 2015 16:57:31 GMT
<
* Ignoring the response-body
* Connection #0 to host localhost left intact
* Issue another request to this URL: 'http://localhost:8888/RestfulDigestSecurityExample/rest/customers/secure/update'
* Re-using existing connection! (#0) with host localhost
* Connected to localhost (127.0.0.1) port 8888 (#0)
* Server auth using Digest with user 'user1'
> PUT /RestfulDigestSecurityExample/rest/customers/secure/update HTTP/1.1
> Authorization: Digest username="user1", realm="UserDatabase", nonce="1449161851859:1132c63829013066e5d9e7cbd532a6dd", uri="/RestfulDigestSecurityExample/rest/customers/secure/update", cnonce="MjU3NzEx", nc=00000001, qop="auth", response="3d3fc7ef13957ebba7e033a3b4b35a86", opaque="44426A180C3A3D7DBCC153ACDA7F5958"
> User-Agent: curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.14.0.0 zlib/1.2.3 libidn/1.18 libssh2/1.4.2
> Host: localhost:8888
> Accept: */*
> Content-Type: application/json
> Content-Length: 122
>
< HTTP/1.1 200 OK
< Server: Apache-Coyote/1.1
< Cache-Control: private
< Expires: Wed, 07 Feb 1969 19:00:00 EST
< Content-Type: application/json
< Transfer-Encoding: chunked
< Date: Thu, 07 Feb 2015 16:57:31 GMT
<
* Connection #0 to host localhost left intact
* Closing connection #0

{"id":102,"name":"Jermaine Z. Holston","address":"17852 Cedar Lane","city":"Princeton","state":"New Jersey","zip":"08540"}

Download the Complete Source Code

That’s It!

I hope you enjoyed this tutorial. It was certainly a lot of fun putting it together and testing it out. Please continue to share the love and like us so that we can continue bringing you quality tutorials. Happy Coding!!!

java_jaxrs_digest_security

Related JAX-RS Tutorial Posts

  • RESTful Web Services with AngularJS, Bootstrap and Java using JAX-RS and Jersey
    In this tutorial we will develop a full blown CRUD application using JAX-RS API and Jersey to implement RESTful web services. JAX-RS stands for Java API for RESTful Web Services and by using this powerful API developers can easily build REST services. Jersey RESTful Web Services is an open source framework for developing RESTful Web Services in Java that provides support for JAX-RS APIs.
  • JAX-RS Security using JSON Web Encryption(JWE) with AngularJS, Bootstrap, Grid-UI and MongoDB Example
    In this tutorial we will discuss how to use AngularJS, Bootstrap and Grid-UI to connect to secure JAX-RS RESTful web services using JWE/JWT/JWS for Authentication and Authorization. In our example implementation, we will be using Symmetric Encryption where the receiver and sender share a common key.
  • JAX-RS Security using JSON Web Encryption (JWE) with JWS/JWT for Authentication and Authorization
    In this tutorial we will discuss how to secure JAX-RS RESTful web services using JSON Web Encryption(JWE), JSON Web Key (JWK), JSON Web Signature(JWS), and JSON Web Tokens(JWT) for Authentication and Authorization. JSON Web Encryption (JWE) encrypted content using Javascript Object Notation (JSON) based structures.
  • JAX-RS Security using JSON Web Tokens (JWT) for Authentication and Authorization
    In this tutorial we will discuss how to secure JAX-RS RESTful web services using JSON Web Tokens Authentication and Authorization. This form of security is used for authenticating a client using a signed token which can be verified by application servers. This token-based form of security is a ideal candidate for Cross-domain (CORS) access and when server-side scalability is a prime motivation factor.
  • JAX-RS Security using API-KEY for Authorization
    In this tutorial we will discuss how to secure JAX-RS RESTful web services using API-KEY or Service Key for Authorization. This form of security is used to ensure that certain RESTful endpoints are protected against unauthorized use.
  • JAX-RS Security using Digest Authentication and Authorization
    In this JAX-RS Digest Authentication and Authorization tutorial we will discuss how to set up digest security for our RESTful web service. This form of access authentication is slightly more complex than the previously discussed JAX-RS Basic Authentication Tutorial.
  • JAX-RS Security using Basic Authentication and Authorization
    In this JAX-RS basic authentication and authorization tutorial we will discuss how to set up security for our RESTful web service. We will need to ensure that some of the URIs are protected and only clients that have been authenticated and authorized are able to gain access and make use of them.
  • Upload and Download Multiple Binary Files using MongoDB
    In this tutorial we are going to develop multiple file upload and file download capability using RESTful web service using JAX-RS and Jersey storing the contents of files into MongoDB Database using a powerful feature in MongoDB for managing large files called GridFS.
  • Inserting and Retrieving Binary Data with MongoDB using JAX-RS RESTful Web Service
    In this tutorial we are going to develop file upload and file download capability using RESTful web service using JAX-RS and Jersey storing the contents of files into MongoDB Database using a powerful feature in MongoDB for managing large files called GridFS. The bulk of the framework for this tutorial came from my previous tutorial so you find many similarities between the two posts.
  • Inserting and Retrieving Binary Data with SQL Server Database using JAX-RS RESTful Web Service
    In this tutorial we are going to develop file upload and file download capability using RESTful web service using JAX-RS and Jersey storing the contents of the file into SQL Server Database using BLOB. Our example will be able to store PDF files, Excel files, Word Document files, Powerpoint files, Image files, or any other type of file available us provided we have ample amount of storage space.
  • File Download Example Using RESTful Web Service with JAX-RS and Jersey
    In this example we are going to develop file download capability using RESTful web service using JAX-RS and Jersey. As you will see, downloading a File using Jersey is very easy as it uses the HTTP GET for the file operations. In our web service, we will be allowing you to download the file via two mechanisms. You will be able to download by HTTP query parameters via @QueryParam and also by using the path parameters via @PathParam.
  • JAX-RS Restful Web Services with JNDI Datasource for MySQL in Tomcat
    In this tutorial we will discuss how to set up JAX-RS RESTful web services and configure a JNDI Datasource with Connection Pooling in Tomcat and connect to MYSQL Database. JNDI (Java Naming and Directory Interface) provides and interface to multiple naming and directory services.
  • File Upload Example Using RESTful Web Service with JAX-RS and Jersey
    In this example we are going to develop file upload capability using RESTful web service using JAX-RS and Jersey. As you will see, uploading a File using Jersey is pretty straight forward as it uses HTTP POST with the encoding type of multipart/form-data for the file operations.
  • RESTful Web Services @FormParam Example using JAX-RS and Jersey
    In this example we are going to develop a simple RESTful web service using JAX-RS and Jersey to extract form parameters submitted by a form using @FormParam annotation.
  • RESTful Web Services @MatrixParam Example using JAX-RS and Jersey
    In this example we are going to develop a simple RESTful web service using JAX-RS and Jersey to extract matrix parameters from the request URL using the @MatrixParam annotations.
  • RESTful Web Services @QueryParam Example using JAX-RS and Jersey
    In this example we are going to develop a simple RESTful web service using JAX-RS and Jersey to extract query parameters from the request URL using the @QueryParam annotation.
  • RESTful Web Services @PathParam Example using JAX-RS and Jersey
    In this example we are going to develop a simple RESTful web service using JAX-RS and Jersey to extract path parameters from the request URL using the @PathParam annotation.

Please Share Us on Social Media

Facebooktwittergoogle_plusredditpinterestlinkedinmail

Leave a Reply

Your email address will not be published. Required fields are marked *