Friday 29 June 2012

Spring Property Place Holder

Basic spring configuration makes using property files and their key-value pairs really easy!

property-placeholder

The most simple way to do this is to use the property-placeholder tag.  This is as simple as including the line,

    <context:property-placeholder location="classpath:app.properties"/>

However, sometimes it is easier to have a list of properties files.  This can simply be done by giving a comma separated list in the example above,

    <context:property-placeholder location="classpath:app.properties,classpath:alt_app.properties"/>

This is starting to get a bit unclear though.  Perhaps a better way is to no longer use the spring property-placeholder and instead use the 'full' bean version.

 PropertyPlaceholderConfigurer

This 'full' bean version is the PropertyPlaceholderConfigurer class and can be used like this,

    <bean id="appProperties" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
            <list>
                <value>classpath:app.properties</value>
                <value>classpath:alt_app.properties</value>
            </list>
        </property>
        <property name="ignoreResourceNotFound" value="true" />
        <property name="ignoreUnresolvablePlaceholders" value="false" />
    </bean>

This is, to my mind at least, rather more clear.  Spring will mash all the properties file together and present them as a single set of properties.  It will also override values with those found in later files if the keys are the same.  This is a really useful function as you can then specify some items to be overridden but not necessarily all!

We also get to set the ignoreResourceNotFound and ignoreUnresolvablePlaceholders values.

ignoreResourceNotFound:  If a property file cannot be found then spring won't throw an error
ignoreUnresolvablePlaceholders: If a key cannot be found then it is ignored and no error is thrown.

Having ignoreResourceNotFound=true is sensible because you may choose to put in place the ability to override a default properties file but not necessarily populate it.  However, you would normally want all the keys to be defined somewhere so having the ignoreUnresolvablePlaceholders=false is probably going to help diagnose problems.

Referencing a value

A key-value pair can be referenced using the ${key_name} notation.  This can also be used to get properties configured in the jvm with -Dmyprop=value or set into the application server.

Using the PropertyPlaceholderConfigurer you can also set the prefix and suffix characters so that you can specify

        <property name="placeholderPrefix" value="$myapp{" />
        <property name="placeholderSuffix" value="}" />

and then reference your key-value pairs as $myapp{key_name} - or whatever you want.  This is useful where you may have different properties files to control different aspects of your application and you don't necessarily want to leak properties between them.  For example keeping security settings separate.

Tuesday 19 June 2012

Spring Security

Spring Security

Spring have done a brilliant security framework for securing pages and elements of a website simply and easily.

Concept

The concept is very straightforward.  Certain resources / pages need to be secured while others don't.  The spring framework deals with all this though a filter chain.  This means that no configuration is necessary in the controllers or jsp pages.  In testing for a login failure is impossible in a Controller because the filter takes care of it before the controller is given the request by the MessageDispatcherServlet!  Remember though that because it is a servlet filter that a few extra bits are necessary!

web.xml

As noted above the spring-security framework is a filter.  Therefore the filter needs to be added to the web.xml file so that the deployment container knows about it.  There are two entries here.  The latter clearly enables spring-security.  The first entry however is really important.  Without it the scope="request" is not possible for beans because that scope is only valid with the MessageDispatcherServlet.  Therefore to allow for session scope this additional filter must be put into the web.xml page.  Unfortunately ordering is important here.  The RequestContextFilter must be before the security filter.  This is obvious really!  If the filters are dealt with in turn then the RequestContextFilter needs to make the request scope available before the security framework filter.


    <filter>
        <filter-name>requestContextFilter</filter-name>
        <filter-class>org.springframework.web.filter.RequestContextFilter
        </filter-class>
    </filter>
    <filter-mapping>
        <filter-name>requestContextFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <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>

Maven Dependencies

The maven dependencies required for the spring-security framework are as follows


        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-web</artifactId>
            <version>3.1.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-config</artifactId>
            <version>3.1.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-ldap</artifactId>
            <version>3.1.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-taglibs</artifactId>
            <version>3.1.0</version>
        </dependency>

At the time of writing the current version is 3.1.0, however, have a look at the maven public repo to find the latest version. Search the repo at http://search.maven.org or specifically for spring-security at http://search.maven.org/#browse|875588238.

spring-context.xml

This is where the behaviour configuration starts.  It is pretty easy to get the behaviour exactly as you want it.  Here is an example,

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:sec="http://www.springframework.org/schema/security"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="
           http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/security
        http://www.springframework.org/schema/security/spring-security-3.1.xsd    
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <sec:http pattern="/resources/**" security="none" />
    <sec:http pattern="/login" security="none" />

    <sec:http access-denied-page="/login?access=denied" use-expressions="true" >  
        <sec:intercept-url pattern="/app/**" access="hasAnyRole({'APP_USER','APP_ADMIN'})" />
        <sec:intercept-url pattern="/app/admin/**" access="hasRole('APP_ADMIN')" />
        <sec:intercept-url pattern="/**" access="denyAll" />
        <sec:form-login login-page="/login"  authentication-success-handler-ref="authenticationSuccessHandler" authentication-failure-handler-ref="authenticationFailureHandler"/>
        <sec:logout logout-success-url="/login" invalidate-session="true" />
    </sec:http>

    <sec:authentication-manager>
        <sec:authentication-provider ref="activeDirectoryAuthProvider"></sec:authentication-provider>
    </sec:authentication-manager>
   
    <bean id="authenticationSuccessHandler" class="app.login.AppAuthenticationSuccessHandler">
        <property name="alwaysUseDefaultTargetUrl" value="false" />
        <property name="defaultTargetUrl" value="/app/home" />
    </bean>
   
    <bean id="authenticationFailureHandler" class="app.login.AppAuthenticationFailureHandler">
        <property name="defaultFailureUrl" value="/login?access=denied" />
    </bean>
   
    <bean id="appGrantedAuthoritiesMapper" class="app.login.AppGrantedAuthoritiesMapper" />

    <bean id="activeDirectoryAuthProvider" class="org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider">
        <constructor-arg value="myapp.com" />
        <constructor-arg value="ldap://myapp.com:389/" />               
        <property name="authoritiesMapper" ref="appGrantedAuthoritiesMapper" />
        <property name="useAuthenticationRequestCredentials" value="true" />
    </bean>

Here is some explanation...

<sec:http pattern="/resources/**" security="none" /> - This means that anything in the /resources/ is available.  css, images, js should live here as these don't need to be secured and in fact if you secure them it means you can't style your login page properly.

<sec:http pattern="/login" security="none" /> - Obviously you can't secure your login page because otherwise someone can't log in!!

<sec:http access-denied-page="/login?access=denied" use-expressions="true" > - the login page maps to a jsp (through a controller) therefore an error message can be added if the param access=denied is there.  So the access denied page sends the user back to the login page so that they can try again, with the addition of a failure message somewhere on the screen.

<sec:intercept-url pattern="/app/**" access="hasAnyRole({'APP_USER','APP_ADMIN'})" /> - any url from /app/ downwards can only be accessed by people in particular roles.  In this case the roles are 'APP_USER' or 'APP_ADMIN'.

<sec:intercept-url pattern="/app/admin/**" access="hasRole('APP_ADMIN')" /> - only users in the APP_ADMIN role can view urls beneath /app/admin.

<sec:intercept-url pattern="/**" access="denyAll" /> - All other pages are denied!

<sec:form-login login-page="/login"  authentication-success-handler-ref="authenticationSuccessHandler" authentication-failure-handler-ref="authenticationFailureHandler"/> - The login page is at the url /login.  When a login is successful then use the authenticationSuccessHandler bean, when login has failed use the authenticationFailureHandler bean (see later for examples and reason).

<sec:logout logout-success-url="/login" invalidate-session="true" /> - when the user logs out send them back to the login page at the url /login.

<sec:authentication-manager>
    <sec:authentication-provider ref="activeDirectoryAuthProvider"></sec:authentication-provider> 
</sec:authentication-manager> - Use the activeDirectoryAuthProvider to lookup the users.  ActiveDirectory is Microsoft's implementation of LDAP (pretty much anyway!).  Obviously other types of lookup can be performed.  The spring documentation contains a very simple example of configuring the users in the spring context itself.

Success

The success and failure handlers give access to the flow when certain criteria have been met. In the case of the success you might want to load information about a user from a database or log the fact that they have accessed the system.  A very simple way of doing this is to create a class which extends SimpleUrlAuthenticationFailureHandler and overrides the onAuthenticationSuccess() method.  Both the success and failure handler rely on a response.sendRedirect() to shift the client to the landing page or error page.  However, the SimpleUrlAuthenticationFailureHandler takes a defaultTargetUrl in the spring configuration so all that is necessary is to call super.onAuthenticationSuccess() in the subclass and everything is done for you!

    <bean id="authenticationSuccessHandler" class="app.login.AppAuthenticationSuccessHandler">
        <property name="alwaysUseDefaultTargetUrl" value="false" />
        <property name="defaultTargetUrl" value="/app/home" />
    </bean>

 



 Failure & Ajax


The failure mechanism acts exactly the same way.  Normally there is no need to override the success and failure as the standard behaviour is perfectly adequate.  However, where you have ajax requests there is a specific problem.  In the situation where ajax requests may access a session which is timed out then there is a redirect by spring to the login page.  This is a problem  for the client as it is probably expecting xml or json objects to be returned but instead will get html.  The cure for this is to create a custom AuthenticationFailureHandler such as that below,

public class AppAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler
{

    /**
     * {@inheritDoc}
     *
     * Looks at the request url and if this contains the "X-Requested-With" header which is the de-facto standard for ajax libraries.
     */
    @Override
    public void onAuthenticationFailure(final HttpServletRequest request, final HttpServletResponse response,
            final AuthenticationException authException) throws ServletException, IOException
    {

        final String requestedWith = request.getHeader("X-Requested-With");

        if (requestedWith != null && requestedWith.equals("XmlHttpRequest"))
        {
            response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
        }
        else
        {
            super.onAuthenticationFailure(request, response, authException);
        }
    }
}

This works because Ajax requests have the 'X-Requested-With' http header.  This can be examined and if it exists return a 401 (or something) to the client.  Bare in mind that authentication has already failed at this point so now you are just deciding what to do.  This method will allow Ajax clients to check for the response code as a safe way of making sure there is no timeout.



Wednesday 13 June 2012

SQL Server & Tomcat

JTDS Library

It is necessary sometimes to connect Tomcat to MS SQL server using SSO from the user currently logged into the windows machine they are on.  This is possible with the jtds (http://jtds.sourceforge.net/) library.  This brilliant library requires a small dll file (ntlmauth.dll) to be put on the system path (eg jre/bin) and the jtds jar file to be put into the tomcat lib directory.  The dll interacts with Windows to get the user credentials and the jtds jar does the normal jdbc connection bits.

Tomcat context.xml

The context file now needs to have the resource added.  The username and password elements are not required if you want the SSO.


    <Resource
       name="jdbc/myDS"
       auth="Container"
       type="javax.sql.DataSource"
       maxActive="100"
       maxIdle="30"
       maxWait="10000"
       driverClassName="net.sourceforge.jtds.jdbcx.JtdsDataSource"
       url="jdbc:jtds:sqlserver://<servername>:<port>/<databasename>;instance=<instance>;
          domain=<userdomain>"/>

It is necessary to specify the instance because the SQL Server may specify a

    Server name: servername\instance

but this isn't a valid network servername.  Therefore this has to be split into two parts.  The actual server name and the instance.  The port is usually 1433 for SQL Server.



Friday 8 June 2012

Tiles Tutorial / Setup

Tiles

Tiles is a layout technology which carves pages into different sections or 'tiles'.  These can then be controlled and set using an xml file.  The easiest way to see this is just from a simple example.

Basic Tiles Config

The basic tiles configuration is an xml file (or multiple files) which defines the layouts.


<!DOCTYPE tiles-definitions PUBLIC
       "-//Apache Software Foundation//DTD Tiles Configuration 3.0//EN"
       "http://tiles.apache.org/dtds/tiles-config_3_0.dtd">
      
<tiles-definitions>

    <!-- Main layout -->
    <definition name="myapp.main" template="/WEB-INF/views/main.jsp">
        <put-attribute name="header" value="
/WEB-INF/views/header.jsp" />
        <put-attribute name="footer" value="
/WEB-INF/views/footer.jsp" />
    </definition>

    <definition name="myapp.home" extends="
myapp.main">
        <put-attribute name="body" value="
/WEB-INF/views/home.jsp" />
    </definition>

</tiles-definitions>

JSP Layout

The main.jsp page above is a standard JSP page which has a couple of 'holders' for the tiles elements.

    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles" %>

    <html>
       <head />
        <body> 
            <!-- header -->
            <div class="header">
                <tiles:insertAttribute name="header" />
            </div>
             
            <!-- Central Container -->
            <div class="main_content">
                <tiles:insertAttribute name="body" />
            </div>
             
            <!-- footer -->
            <div class="footer">
                <tiles:insertAttribute name="footer" />
            </div>
        </body>
    </html>

Here you can see that the 'tiles' elements are brought in by the tiles tag.  These place holders are resolved by the xml file configuration for the page that has been requested. The ModelAndView will control the tiles name that is to be used.

Controller

The ModelAndView which is returned by the Controller will define the view to use based on the definition name in the tiles configuration.  For example


    ModelAndView mav = new ModelAndView("myapp.home");

This will use the 'myapp.home' definition which itself extends the 'myapp.main' definition.  As a result the full page is rendered using this hierarchy.

Spring Config

Finally the spring configuration needs to be told how to resolve the view name.  This is standard with spring, whether it is jsp view resolver, Freemarker, etc.  For tiles the configuration looks like this,

    <!-- Configure Tiles -->
    <bean id="tilesConfigurer" class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">

        <property name="definitions">
            <list>
                <value>/WEB-INF/tiles/myapp.xml</value>
            </list>
        </property>

        <property name="preparerFactoryClass"
                  value="org.springframework.web.servlet.view.tiles2.SpringBeanPreparerFactory"/>
    </bean>

    <bean id="viewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
        <property name="viewClass" value="org.springframework.web.servlet.view.tiles2.TilesView"/>
    </bean>

Here the 'tileConfigurer' gives a list of the definitions that are used.  This means that the definitions can be split into logical lumps and you don't end up with a file which is unmanageably large!  The 'viewResolver' is a standard spring element which tells spring how to resolve the view name.

Maven

Maven dependencies,

  <dependency>
    <groupId>org.apache.tiles</groupId>
    <artifactId>tiles-extras</artifactId>
    <version>3.0.4</version>
  </dependency>

Preparer Classes

In the situation of having a menu defined in Tiles you don't want to have to remember to get every controller to put particular elements in the model. An easy way of extracting this is to use a ViewPreparer. Implement the ViewPreparer interface and complete the execute() method.  Then in the tiles definition you can add a preparer="myAppPreparer"

    <!-- Main layout -->
    <definition name="myapp.main" template="/WEB-INF/views/main.jsp" preparer="myAppPreparer">
        <put-attribute name="header" value="
/WEB-INF/views/header.jsp" />
        <put-attribute name="footer" value="
/WEB-INF/views/footer.jsp" />
    </definition>

The preparer name here is a fully qualified path name by default but can be a spring bean and therefore have its dependencies injected by spring. To make spring resolve these beans you need to have the 'preparerFactoryClass' configured in the spring tilesConfigurer(see above).

The HttpServletRequest can be obtained within a ViewPreparer as follows,

    /**
     * {@inheritDoc}
     */
    @Override
    public void execute(final TilesRequestContext tilesRequestContext, final AttributeContext attributeContext)
    {
        final HttpServletRequest request = (HttpServletRequest) tilesRequestContext.getRequestObjects()[0];
        ... other code to add to the request ...
    }

Loose Ends

There are occasions when a url is required within the application or spring context and the url needs to be mapped to the tiles names.  This is possible by using a spring mvc:controller

  <mvc:view-controller path="my_url" view-name="my.tiles.definition"/>

This then allows the 'my_url' to be used within the application and context.

Thursday 7 June 2012

Basic JSP Tags

Basic JSP Commands

Here are a load of basic jsp tags that I'll add to over time.  Initially though, it'll just cover the real basics

In a JSP page there are certain elements which are always available.  These include

request - HttpServletRequest
session - HttpSession

For example to view the username of the currently logged in user you can use

    <%= request.getUserPrincipal().getName() %>

You can also do this with the c:out command below if you use the pageContext first.

JSP Tags

To use the basic JSP tags you'll need to include the import at the top of the jsp page.

    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>  
 

c:out

Use this to 'print' to the screen eg

    <c:out value="${modelValue}"/>

where modelValue is put into the ModelMap in the controller.

c:if

Use this to conditionally add items

    <c:if test="${myValue == 'Value'}">
        do something
    </c:if>

c:choose / c:when / c:otherwise

This is the equivalent to the if - else if - else statement

    <c:choose>
        <c:when test="${myValue == 'Value'}">
            do something
        </c:when>
        <c:when test="${myValue == 'AnotherValue}">
            do something else
        </c:when>
        <c:otherwise>
            do the fall back action
        </c:otherwise>
    </c:choose>

c:url

This is a really useful tag which allows you to just create a link and the tag will take care of the server name, port and application context

    <c:url value="/my_link" />

you can also add attributes

    <c:url value="/my_link"> 
        <c:param name="link" value="${linkId}" /> 
    </c:url>

c:forEach

This is a basic iterator for looping through lists etc

    <c:forEach var="item" items="${itemList}" varStatus="status">

        ${status.first ? 'Start' : ''}

        ${status.index}: ${item.name}

        ${status.last ? 'End' : ''}

    </c:forEach>

c:set

It is occasionally necessary to create a variable that is used by other jsp commands or tags. You can do this by using the c:set tag, for example

    <c:set var="linkId" value="${param.link}"/>
You can set different scopes for these by using the scope="..." attribute,
    <c:set var="linkId" scope="session" value="${param.link}" />
but by default it is page-scope only.