Friday, 28 September 2012

Installing HSQL on Amazon EC2

Recently we were required to develop a web application for a client and deploy on Apache Tomcat hosted on Amazon EC2. The application had very simple persistence requirements as it mostly dealt with integrating content from various sources such as web services. Therefore we decided to use HSQL as the database. It took a while to set up HSQL on Amazon as initially the application just couldn't connect to the database although it had been installed correctly (caused by having different versions of the hsqldb.jar file in the web app and deployed on EC2). This post will hopefully reduce the pain of anyone attempting the same.

I'm assuming you have correctly installed hsql via "sudo yum install"
As hsql is installed without a password by default, the first thing you need to do is set the password for the db.
  1. Navigate to the hsql installed directory "cd /var/lib/hsqldb"
  2. Start the db using  "sudo java -cp lib/hsqldb.jar org.hsqldb.Server - database.0 file:data/db0 -dbname.0 firstdb &" This will start the database with an alias of "firstdb" and create the files under the "data" directory.
  3. The next step use the command line sql tool to access the db.
  4. Copy the "sqltool.rc" file from the hsqldb directory to the user's home directory "cp /var/lib/hsqldb/sqltool.rc ~/sqltool.rc"
  5. Execute the following command to start the tool : "java -jar /var/lib/hsqldb/lib/hsqldb.jar db0-url" This will provide an "sql>" prompt.
  6. Now set the password "sql> set PASSWORD password;" (syntax may not be 100% correct)
  7. Now shutdown the database "sql> shutdown;"
  8. Quit the sqltool "sql> \q"
  9. At this stage the hsqldb should have been shutdown correctly with the new password configured. Restart the hsql database as before in step 1 and 2.
  10. To check that the password has been changed, try accessing the database with the sqltool again from step 5. It should fail to connect.
  11. From the home directory, edit sqltool.rc to change the password used to access the database. "vi sqltool.rc"
  12. Find the urlid db0-url that represents your db. It has 4 properties: urlid, url, username and password. The value for password is probably empty so change that to "password". Save and exit vi.
  13. Now try accessing the database again from step 5. It should connect successfully.

Securing Web Applications with Spring Security

This post will demonstrate how to configure a web application with Spring Security. In our experience Spring Security provides a far more elegant approach to security than the standard JEE spec.

Assuming a web application has been developed using Spring MVC, there will be a web.xml file and a number of Spring configuration files. To enable Spring Security, we need to configure the Spring DelegatingFilterProxy filter in the web.xml.



    <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>


This filter is a proxy that delegates to a Spring-managed bean that implements the Filter interface. The name of the filter matches the name of the bean in the Spring context file. The security filter chain intercepts requests and enforces any security requirements specified in the Spring context file as shown below:


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

<beans:beans xmlns="http://www.springframework.org/schema/security"
    xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd">
    <!-- HTTP security configurations -->
    <http auto-config="true" use-expressions="true">
        <form-login login-processing-url="/resources/j_spring_security_check" login-page="/login" authentication-failure-url="/login?login_error=t" />
        <logout logout-url="/resources/j_spring_security_logout" />
        <!-- Configure these elements to secure URIs in your application -->


        <intercept-url pattern="/admin/authoriseusers/**" access="hasRole('ROLE_ADMIN')" />

        <intercept-url pattern="/member/**" access="isAuthenticated()" />
        <intercept-url pattern="/resources/**" access="permitAll" />
        <intercept-url pattern="/**" access="permitAll" />
    </http>
    <!-- Configure Authentication mechanism -->
    <authentication-manager alias="authenticationManager">
        <!-- SHA-256 values can be produced using 'echo -n your_desired_password | sha256sum' (using normal *nix environments) -->
        <authentication-provider>
            <password-encoder hash="sha-256" />
            <user-service>
                <user name="admin" password="8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918" authorities="ROLE_ADMIN" />
                <user name="user" password="04f8996da763b7a969b1028ee3007569eaf3a635486ddab211d512c85b9df8fb" authorities="ROLE_USER" />
            </user-service>
        </authentication-provider>
    </authentication-manager>
</beans:beans>

This shows a sample security configuration with an in-memory userstore. Note that the Spring Security uses its own XML namespace that has been declared as the default namespace at the beginning of the context file. It then sets up the http security with form-based login and a number of intercept-url elements that specify which paths should be secured and which roles granted access. This is where all the access control requirements can be configured. There are additional properties that can specify the HTTP method that needs to be secured for the given URI. Next we configure an authentication manager with an authentication provider that basically controls how users will be authenticated by Spring Security. In this case, it is simply using an in-memory authentication provider where user's have been defined with their name, password and roles.

The http form-login configuration specifies the login-page and the url for the page to display on authentication failure. The excerpt below shows the form from the login page. Note the form's action property.


<form action="/resources/j_spring_security_check" method=post>
  <div>
    <label for="j_username">Please Enter Your Name:</label>
  </div>
  <div>   
    <input id="j_username" type="text" name="j_username" size="25">
  </div>
  <div>
    <label for="j_password">Please Enter Your Password:</label>
  </div>
  <div>
    <input type="password" size="15" name="j_password">
  </div>
  <div>
       <input type="submit" value="Submit">
       <input type="reset" value="Reset">
    </div>
</form>
 


Now whenever an user accesses one of the secured URIs, Spring Security will require the user to login via the configured login page. On submitting the credentials, Spring Security will authenticate using the configured authentication provider.

Using an in-memory user store only serves demonstration purposes and so the following section shows a how a custom authentication provider can be specified that allows control over how users are authenticated.



  <beans:bean id="myAuthenticationProvider" class="javaworkbench.usermanagement.authentication.AuthenticationProvider" />

  <!-- Configure Authentication mechanism -->
  <authentication-manager alias="authenticationManager" >
    <authentication-provider ref="myAuthenticationProvider" />
  </authentication-manager>


The custom AuthenticationProvider class extends a base Spring AuthenticationProvider that responds to UsernamePasswordAuthenticationToken authentication requests.


public class AuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {

       @Autowired
       private IdentityManager identityManager;

       @Override
       protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authenticationToken)
                     throws AuthenticationException {

       }

       @Override
       protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authenticationToken)
                     throws AuthenticationException {

              String password = authenticationToken.getCredentials().toString();
              User user = identityManager.authenticateAndRetrieveUser(username, password);

              return user;
       }

}


The custom AuthenticationProvider delegates to an IdentityManager that is an interface with implementations for retrieving user data from LDAP and JDBC relational databases.

We have just scratched the surface of Spring Security by showing a basic example. Spring Security provides a great deal of flexibility through various configuration options.