Testing OpenLiberty with Arquillian (Remote)

Having heard many great reviews, I thought I’ll give Open Liberty a try.

In this post, I shall discuss the following:

  • Setup of Open Liberty
  • Setup JDBC connection
  • Setup Arquillian
  • Testing REST endpoint

Installing Open Liberty

At the time of writing, I am using Open Liberty 18.0.0.1, and I am using Java SE 1.8.0_172 (P.S. Keen to move on to Java 9 and Java 10, but I thought better wait for LTS Java 11).

Installation is very easy. Let’s assume we are going to create a running server name test.

First, unpack your Open Liberty download. It will create a directory structure wlp.

Navigate to bin directory and run the following command:

./server create test

Now a server name test has been created. To start:

./server start test

with the argument test being the name of the server.

Navigate to http://localhost:9080/test to see the context root.

To stop,

./server stop test

– Configure server.xml

Once you have start test server, a directory will be created under the /usr/servers/test, and inside that directory there is file named server.xml. Let’s check it out.

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

    <!-- Enable features -->
    <featureManager>
        <feature>jsp-2.3</feature>
    </featureManager>

    <!-- To access this server from a remote client add a host attribute to the following element, e.g. host="*" -->
    <httpEndpoint id="defaultHttpEndpoint"
                  httpPort="9080"
                  httpsPort="9443" />

    <!-- Automatically expand WAR files and EAR files -->
    <applicationManager autoExpand="true"/>
</server>

In this article we are using Java EE 7 Web Profile, to enable that, it is very simple to do that (and it is not even necessary to restart the server). Simply change the featureManager.

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

    <!-- Enable features -->
    <featureManager>
        <feature>webProfile-7.0</feature>
    </featureManager>

    <!-- the rest of the configuration omitted -->

You can check what features being loaded dynamically by looking at console.log.

Configuring JDBC Datasource

– Configure Datasource in server.xml

For this exercise, I am using MySQL 8.0. Setting up MySQL and its configuration is out-of-scope of this article.

Let’s assume we have created a new database, also named test.

To set up your datasource, make the following modification to your server.xml and restart (or not, not too sure on this one, but no harm in restarting).

Comments interleaved.

<?xml version="3.0" encoding="UTF-8"?>
<server description="new server">

    <!-- Enable features -->
    <featureManager>
        <feature>webProfile-7.0</feature>
    </featureManager>

    <!-- Declare the jar files for MySQL access through JDBC. -->
    <dataSource id="testDS" jndiName="jdbc/testDS">
        <jdbcDriver libraryRef="MySQLLib"/>
        <properties databaseName="test"
                  serverName="localhost" portNumber="3306"
                  user="root" password="P4sswordGoesH3r3"/>
    </dataSource>
    <library id="MySQLLib">
        <file name="/home/dwuysan/dev/appservers/wlp/usr/shared/resources/mysql/mysql-connector-java-8.0.11.jar"/>
    </library>

    <!-- Automatically expand WAR files and EAR files -->
    <applicationManager autoExpand="true"/>
</server>

– persistence.xml

OpenLiberty comes with EclipseLink bundled as JPA Provider. In this example I have not configured any EclipseLink’s properties.

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
             version="2.1">
    <persistence-unit name="testPU">
        <jta-data-source>jdbc/testDS</jta-data-source>        
        <properties>
        </properties>
    </persistence-unit>
</persistence>

And you can then call it in your Java EE application via:

@Stateless
@LocalBean
public class LogService {

    @PersistenceContext
    private EntityManager em;

    public Collection<Log> getLogs() {
        return this.em.createNamedQuery(Log.FIND_ALL, Log.class).getResultList();
    }
}

Setting up arquillian

In this article, we are going to implement Arquillian remote testing against a running OpenLiberty server.

Firstly, add arquillian to your pom.xml.

– Configure pom.xml

This is the pom.xml that have been modified:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>id.co.lucyana</groupId>
    <artifactId>test</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <name>test</name>

    <properties>
        <endorsed.dir>${project.build.directory}/endorsed</endorsed.dir>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.jboss.arquillian</groupId>
                <artifactId>arquillian-bom</artifactId>
                <version>1.4.0.Final</version>
                <scope>import</scope>
                <type>pom</type>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>        
        <dependency>
            <groupId>org.jboss.arquillian.graphene</groupId>
            <artifactId>graphene-webdriver</artifactId>
            <version>2.3.2</version>
            <type>pom</type>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-java</artifactId>
            <scope>test</scope>
            <version>3.12.0</version>
        </dependency>
        <dependency>
            <groupId>org.jboss.arquillian.junit</groupId>
            <artifactId>arquillian-junit-container</artifactId>
            <scope>test</scope>
        </dependency>        
        <dependency>
            <!-- Arquillian WebSphere Liberty Profile support -->
            <groupId>io.openliberty.arquillian</groupId>
            <artifactId>arquillian-liberty-remote</artifactId>
            <version>1.0.0</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-web-api</artifactId>
            <version>7.0</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
    
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.7.0</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <compilerArguments>
                        <endorseddirs>${endorsed.dir}</endorseddirs>
                    </compilerArguments>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>3.2.1</version>
                <configuration>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <version>3.1.0</version>
                <executions>
                    <execution>
                        <phase>validate</phase>
                        <goals>
                            <goal>copy</goal>
                        </goals>
                        <configuration>
                            <outputDirectory>${endorsed.dir}</outputDirectory>
                            <silent>true</silent>
                            <artifactItems>
                                <artifactItem>
                                    <groupId>javax</groupId>
                                    <artifactId>javaee-endorsed-api</artifactId>
                                    <version>7.0</version>
                                    <type>jar</type>
                                </artifactItem>
                            </artifactItems>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

– Make modification to server.xml

The documentation provided here is quite self-explanatory. Please consult this documentation for more up-to-date information on how to enable remote-testing.

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

    <!-- Enable features -->
    <featureManager>
        <feature>webProfile-7.0</feature>
        <feature>restConnector-2.0</feature>
    </featureManager>
    
    <!-- Declare the jar files for MySQL access through JDBC. -->
    <dataSource id="testDS" jndiName="jdbc/testDS">
        <jdbcDriver libraryRef="MySQLLib"/>
        <properties databaseName="test" 
                  serverName="localhost" portNumber="3306" 
                  user="root" password="P4sswordGoesH3r3"/>
    </dataSource>
    <library id="MySQLLib">
        <file name="/home/dwuysan/dev/appservers/wlp/usr/shared/resources/mysql/mysql-connector-java-8.0.11.jar"/>
    </library>

    <httpEndpoint httpPort="9080" httpsPort="9443" id="defaultHttpEndpoint" host="*" />

    <!-- userName and password should also be set in arquillian.xml to these values -->
    <quickStartSecurity userName="admin" userPassword="admin" />

    <!-- Enable the keystore -->
    <keyStore id="defaultKeyStore" password="password" />

    <applicationMonitor updateTrigger="mbean" />
    <logging consoleLogLevel="INFO" />

    <!-- This section is needed to allow upload of files to the dropins directory, the remote container adapter relies on this configuration -->
    <remoteFileAccess>
        <writeDir>${server.config.dir}/dropins</writeDir>
    </remoteFileAccess>

    <!-- Automatically expand WAR files and EAR files -->
    <applicationManager autoExpand="true"/>
</server>

– Trust the server (i.e. certificate)

You need to have those keys trusted by your client as well, otherwise you’ll see SSL certificate trust errors, and you need to give permissions for the container adapter to write to the dropins directory” (Liberty-Arquillian 2018)

Once you have made all the necessary modification above, (and re-start the server), notice that there is a new directory created under <location of your OpenLiberty server>/usr/servers/test/resources/security with test being the name of the server we have initially created.

Notice there are two files being created, keys.jks and ltpa.keys. Now, we are interested in the keys.jks.

So that we can run our test from Netbeans (Maven), the JDK must trust the running OpenLiberty.

Check the certificate

keytool -list -v -keystore key.jks
Enter keystore password: 

The password here is basically what we created in our server.xml, particularly this line:

<!-- Enable the keystore -->
<keyStore id="defaultKeyStore" password="password" />

so, enter the password, and the output should be as follows:

*****************  WARNING WARNING WARNING  *****************
* The integrity of the information stored in your keystore  *
* has NOT been verified!  In order to verify its integrity, *
* you must provide your keystore password.                  *
*****************  WARNING WARNING WARNING  *****************

Keystore type: jks
Keystore provider: SUN

Your keystore contains 1 entry

Alias name: default
Creation date: May 26, 2018
Entry type: PrivateKeyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=localhost, OU=test, O=ibm, C=us
Issuer: CN=localhost, OU=test, O=ibm, C=us
Serial number: 2a6c5b27
Valid from: Sat May 26 12:24:30 WITA 2018 until: Sun May 26 12:24:30 WITA 2019
Certificate fingerprints:
	 MD5:  63:92:B2:4A:25:E3:BB:3B:96:37:11:C1:A7:25:38:B5
	 SHA1: B6:38:95:88:FC:50:EC:A0:8E:41:4E:DE:B5:D4:8B:85:2E:61:A2:5F
	 SHA256: 9C:7B:6A:FA:46:8C:50:F2:7D:7B:C4:24:4B:15:78:5A:34:25:C8:43:D1:AB:4D:EE:C7:00:4C:AF:30:F5:5C:92
Signature algorithm name: SHA256withRSA
Subject Public Key Algorithm: 2048-bit RSA key
Version: 3

Extensions: 

#1: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: 88 F2 C2 32 73 73 B6 66   8F FA 42 85 1F 43 A5 AF  ...2ss.f..B..C..
0010: 84 33 62 D5                                        .3b.
]
]



*******************************************
*******************************************

Next, export the certificate

We now need to create a .cer. Use the following command:

keytool -export -alias default -file testwlp.crt -keystore key.jks
Enter keystore password:

Basically we are exporting the certificate of alias into a file named testwlp.crt. Now, a file named testwlp.crt should be created.

Lastly, let’s trust that certificate by importing that certificate into the JDK cacert

keytool -import -trustcacerts -keystore $JAVA_HOME/jre/lib/security/cacerts -storepass changeit -alias testwlp -import -file testwlp.crt

P.S. Please note that, as pointed out by many experts (via Twitter), apparently there are many ways to ‘trust’ the server. I am sure there are better ways, and as much as possible I’d prefer not to touch any of the JDK’s files.

– Create arquillian.xml

Now all those plumbing works done, let’s add arquillian.xml accordingly.

<?xml version="1.0" encoding="UTF-8"?>
<arquillian xmlns="http://jboss.org/schema/arquillian" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://jboss.org/schema/arquillian http://jboss.org/schema/arquillian/arquillian_1_0.xsd">
    <engine>
        <property name="deploymentExportPath">target</property>
    </engine>
    <container qualifier="liberty-remote" default="true">
        <configuration>
            <property name="hostName">localhost</property>
            <property name="serverName">test</property>

            <!-- check the 'quickStartSecurity' on 'server.xml' -->
            <property name="username">admin</property>
            <property name="password">admin</property>

            <!-- check the 'server.xml' -->
            <property name="httpPort">9080</property>
            <property name="httpsPort">9443</property> 
        </configuration>
    </container>    
    <extension qualifier="webdriver">
        <!--<property name="browser">firefox</property>-->
        <property name="remoteReusable">false</property>
    </extension>
</arquillian>

Write a REST Test case

With all those setups done, you can now write an Arquillian Test case. Below is an example of a test case against a JAX-RS end point (Please excuse the simplicity of the test case, the point is to show how we can test using Arquillian-remote against OpenLiberty):

package id.co.lucyana.test.resource;

import id.co.lucyana.test.entity.Log;
import id.co.lucyana.test.services.LogService;
import id.co.lucyana.test.util.ApplicationConfig;
import java.net.URL;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.container.test.api.RunAsClient;
import org.jboss.arquillian.drone.api.annotation.Drone;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.arquillian.test.api.ArquillianResource;
import org.jboss.shrinkwrap.api.ArchivePaths;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.openqa.selenium.WebDriver;

@RunWith(Arquillian.class)
public class LogResourceTest {
    
    @Drone
    private WebDriver webDriver;

    @Deployment
    public static JavaArchive createTestArchive() {
        return ShrinkWrap.create(JavaArchive.class)
                .addClass(Log.class)
                .addClass(LogResource.class)
                .addClass(LogService.class)
                .addClass(ApplicationConfig.class)
                .addAsManifestResource("test-persistence.xml",
                        ArchivePaths.create("persistence.xml"));
    }

    @Test
    @RunAsClient
    public void testLogResource(@ArquillianResource URL url) {        
        this.webDriver.get(url.toString() + "resources/log");
        String pageSource = this.webDriver.getPageSource();
        System.out.println("RESULT: " + pageSource);
        Assert.assertTrue(true);
    }
}

References

DigiCert, 2018, ‘How to install the trusted root into Java cacerts Keystore’, DigiCert, accessed on 20 June 2018

Liberty-Arquillian, 2018, ‘Arquillian Liberty Remote Documentation’, GitHub. Inc, accessed on 20 June 2018

SSLShopper, 2008, ‘The Most Common Java Keytool Keystore Commands’, SSLShopper, accessed on 20 June 2018

Advertisements

JAAS-secured JAX-RS end point

With the advent of RESTFUL (JAX-RS) as the “preferred” way to create web service end points, for a long time I have always wondered how people implement security mechanism around it.

At the end of the day, I presume the underlying implementation of JAX-RS is servlet, and therefore its security might also be around what is already provided by the container, i.e. JAAS.

This post will cover my findings on how to step-by-step implement FORM-based security using JDBC realm, JAX-RS and how to test it using cURL, on Glassfish 3.

Setting up JDBC-realm

Firstly, since we are using JDBC-realm, let’s assume that we have created a JDBC connection to the underlying database under the JNDI jdbc/test.

The next step is to create a new realm. You can do this by going to server-config > Security > Realms and add a new realm. Select the realm type com.sun.enterprise.security.auth.realm.jdbc.JDBCRealm, and then populate the mandatory fields.

  • Start by giving your new realm a name.
  • For JAAS Context, put jdbcRealm
  • Populate JNDI name, preferably starts with "jndi/"

Next, do pay attention to the rest of the fields. It seems that Glassfish expects to see two tables. The first table is to contain a list of users, with usernames as their unique identifier. The second table is to list the groups that each user belongs to. Username is to be the foreign-key link between the two tables. (The next section should give you better idea on how the tables should look, they are after all very simple).

Once these tables are created, we can then populate the mandatory fields accordingly.

Populate database for testing purpose

The next step is to populate the table for testing purpose. Let’s just assume that we will be testing using username hpotter and password test. For the password however, note that Glassfish digest by default is SHA-256, as illustrated by the following screen shot.

sha-256

Hence, you need to encode the password test before insert. You can use encoder by technipixel, which will give you the String 9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08.

The next step is to write some INSERT statements:

INSERT INTO person (id, password, username) VALUES (1, '9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08', 'hpotter');
COMMIT;
INSERT INTO person_role (username, user_group) VALUES ('hpotter', 'User');
INSERT INTO person_role (username, user_group) VALUES ('hpotter', 'Admin');
COMMIT;

Let’s move on to the next step.

Securing web application using JAAS

Quite a number of tutorials out there on JAAS with FORM authentication method. However, I thought I put it here again, with the hope that some might find it simpler.

web.xml

Make the following modification to your web.xml

    <welcome-file-list>
        <welcome-file>/index.jsp</welcome-file><!-- 1 -->
    </welcome-file-list>
    <security-constraint><!-- 2 -->
        <display-name>TestConstraint</display-name>
        <web-resource-collection>
            <web-resource-name>TestResource</web-resource-name>
            <description/>
            <url-pattern>/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <description/>
            <role-name>User</role-name>
            <role-name>Admin</role-name>
        </auth-constraint>
    </security-constraint>
    <login-config><!-- 3 -->
        <auth-method>FORM</auth-method>
        <realm-name>testRealm</realm-name>
        <form-login-config>
            <form-login-page>/login.html</form-login-page>
            <form-error-page>/error.html</form-error-page>
        </form-login-config>
    </login-config>
    <security-role><!-- 4 -->
        <description/>
        <role-name>User</role-name>
    </security-role>
    <security-role><!-- 5 -->
        <description/>
        <role-name>Admin</role-name>
    </security-role>

Let’s go through them one-by-one.

  1. This is the file to be displayed on successful login. You can also use this file as redirection. For example, suppose you have a file called index.xhtml (a JSF page), you can use response.sendRedirect("index.jsf");
  2. This is the actual constraint, i.e. how you secure the application. This section is basically there to secure all access to the application, denoted by /* url pattern, and only allow access of user with the role of User and Admin.
  3. This part denotes that what we are using is FORM authentication method (which I’ll explain in more detail in the next section). Important part is to ensure the correct name of the security realm used, which in this case, testRealm, the same realm name we have given when setting it up via Glassfish admin page. The other part is to set the page containing j_security_check that the application will automatically redirect to in the event of request access has not been authenticated yet.
  4. The known role
  5. Same as previous section.

glassfish-web.xml

We also need to configure glassfish-web.xml so that the container knows about the mapping between groups from the database and the role recognised by the application.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE glassfish-web-app PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Servlet 3.0//EN" "http://glassfish.org/dtds/glassfish-web-app_3_0-1.dtd">
<glassfish-web-app error-url="">
    <security-role-mapping>
        <role-name>Admin</role-name>
        <group-name>Admin</group-name>
    </security-role-mapping>
    <security-role-mapping>
        <role-name>User</role-name>
        <group-name>User</group-name>
    </security-role-mapping>
    <class-loader delegate="true"/>
    <jsp-config>
        <property name="keepgenerated" value="true">
            <description>Keep a copy of the generated servlet class' java code.</description>
        </property>
    </jsp-config>
</glassfish-web-app>

N.B. If you use Netbeans, this file might be generated for you.

Login page: login.html

If we refer again to web.xml above, notice that the login page is pointing to login.html. For FORM authentication method, as per specification, we need to have a form with j_security_check, with j_username and j_password (Oracle 2013).

<!DOCTYPE html>
<html>
    <body>

        <form action="j_security_check" method="post">
            <p>
                <strong>Username</strong>
                <input type="text" name="j_username" size="25" />
            </p>
            <p>
                <strong>Password</strong>
                <input type="password" size="15" name="j_password" />
            </p>
            <p>
                <input type="submit" value="Submit" />
                <input type="reset" value="Reset" />
            </p>
        </form>
    </body>
</html>

With all of these completed, we can start up Glassfish, deploy our application and test it using any browser. Upon accessing the application, users should be directed to login.html to login. Remember to use hpotter as username and test as password. On successful login, the user should be redirected to index.jsp (which in turn redirects user to index.jsf, or anything the index.jsp is redirecting to, according to your requirement).

Create a RESTFUL end point

The next step of course is to create a RESTFUL end point, which is very simple. One of the posts I have written here might also be useful.

To start, assuming we have the following application path.

package com.dwuysan;

import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;

/**
 * @author denywuy
 */
@ApplicationPath(value = "resources")
public class ApplicationConfig extends Application {
}

Let us assume that we have the following simple RESTFUL service.

package com.dwuysan;

import com.dwuysan.entity.Outlet;
import com.dwuysan.service.OutletService;
import javax.annotation.ManagedBean;
import javax.annotation.security.RolesAllowed;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;

@Path(value = "generic")
@RolesAllowed(value = "User")
@ManagedBean
public class GenericResource {

    @Inject
    private OutletService outletService;

    @GET
    @Path("{id}")
    public Outlet get(@PathParam(value = "id") final long id) {
        return this.outletService.getOutlet(id);
    }
}

Note that we have secured this service with javax.annotation.security.RolesAllowed annotation.

Testing secured RESTFUL service using curl

Given the RESTFUL service we created above, we should be able to test it using CURL with the following command:

curl -X GET -H "Accept:application/json" -H "Content-Type:application/json" http://localhost:8080/testApp/resources/generic/101

The above command translate to the following: hit the URL above using GET, with the headers Accept:application/json and Content-Type:application/json (cURL 2013)

Since we have secured our application, invocation as above will not work. The user will be redirected to login.html. Hence, our aim now is to first login. With cURL, we can submit parameters to login, i.e. username and password, and then obtain the cookie. To do that, we can use this command:

curl -b cookies.txt -c cookies.txt -d "j_username=hpotter&j_password=test" http://localhost:8080/testApp/j_security_check

This command is submitting username and password, to the j_security_check (remember our login.html that we have created previously), and storing the cookies obtain under the file cookies.txt.

If you open your cookies.txt, you may see the following:

# Netscape HTTP Cookie File
# http://curl.haxx.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.

#HttpOnly_localhost     FALSE   /testApp     FALSE   0       JSESSIONID      245a317ab91fbb28244403346770

N.B. You might receive Document Moved response. This means login has been successful. Otherwise, you would get the raw html of the error.html again.

Once we have been authenticated successfully, we can use the cookies we have obtained from the login to invoke the RESTFUL service.

curl -X GET -H "Accept:application/json" -H "Content-Type:application/json" -b cookies.txt -c cookies.txt http://localhost:8080/testApp/resources/generic/101

References:

BalusC, 2012, ‘Does JSF support form based security’, accessed 12 February 2013.

Oracle, 2013, ‘Securing Web Application’, accessed 12 February 2013.

Wolff, N, 2005, ‘How do you handle authentication via cookie with CURL?’, accessed 12 February 2013.

Basic Authentication with SOAP Web Service

Nothing new this time around, but I thought I’ll post an entry anyway, more as a reminder for myself in case I need it again.

Every now and then, you would need to invoke a web service end point using basic authentication. I am sure modern frameworks, such as JAX-WS (MKyong 2010), can do this easily.

However, in the unfortunate case you ever find that you would need to manually do this, the formula is to add a header entry as follows (Wikipedia 2012).

Header Value
Authorization Basic (followed by username + ‘:’ + password, encoded in base64)

Assuming that the end point service you would like to invoke has the credentials of username being adumbledore and password being Sherbet Lemon (if you don’t understand, suggest read Harry Potter), then first thing you would want to do is to structure it like this:

adumbledore:Sherbet Lemon

Then, use base64 encoder to encode it. For example, google would suggest this.

Then all you need to do is to add the Authorization header. See the image below.

References:

MKyong, 2010, Application Authentication with JAX-WS, accessed 14 May 2012.

Opinionatedgeek.com, 2012, Base 64 encoder, accessed 14 May 2012.

Wikipedia, 2012, Basic access authentication, accessed 14 May 2012.