Tuesday, June 25, 2013

Externalize Properties File in a Java Web Application

To be able to load properties file from a file system rather than bundling it with your web application you should do the following:

   1.      Define “application base” or “property file location” as a context parameter in web.xml
  <context-param>
      <param-name>app.base</param-name>
      <param-value>file:///c:/my/app</param-value>
  </context-param>



            2.      Load all properties file using Spring’s PropertyPlaceholderConfigurer.
 
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
    <list>
         <value>${app.base}/myapp-app.properties</value>
         <value>${app.base}/myapp-db.properties</value>
    </list>
</property>
</bean>


If you know any other way of doing it, please leave a comment.


Wednesday, December 19, 2012

Web Security: Preventing CSRF attack


CSRF is an attack which forces an end user to execute unwanted actions on a web application in which he/she is currently authenticated. The most commonly used example is "someone tricking you to click on a link to be able to get hold of your logged on banking session and then withdraw money from your bank account without your consent/knowledge." For more information please refer to OWASP CSRF page.[1]

Also, note that CSRF attacks are also known by following names: [1]
  • XSRF
  • Sea Surf
  • Session Riding
  • Hostile Linking
  • One-Click attack (Microsoft)
How much risk?
Based on the Verizon Data Breach Investigation report of 2011 less than 1% of hacking attacks were carried out using CSRF to cause some sort of damage or data loss.

What is the solution?
Fortunately, OWASP has provided a non-invasive solution i.e. CSRFGuard, so that, anyone can protect their application within a matter of few hours if not minutes. The OWASP CSRFGuard library is integrated through the use of a JavaEE Filter and exposes various automated and manual ways to integrate per-session or pseudo-per-request tokens into HTML. When a user interacts with this HTML, CSRF prevention tokens (i.e. cryptographically random synchronizer tokens) are submitted with the corresponding HTTP request. [3]

Implementing CSRFGuard [4]
  1. Download OWASP.CsrfGuard.jar from here and place it under /WEB-INF/lib
  2. Declare CsrfGuard in your web application's deployment descriptor i.e.web.xml as shown below:     <context-param>
            <param-name>Owasp.CsrfGuard.Config</param-name>
            <param-value>WEB-INF/Owasp.CsrfGuard.properties</param-value>
        </context-param>
       
        <context-param>
            <param-name>Owasp.CsrfGuard.Config.Print</param-name>
            <param-value>true</param-value>
        </context-param>
       
        <listener>
            <listener-class>org.owasp.csrfguard.CsrfGuardListener</listener-class>
        </listener>
       
        <filter>
            <filter-name>CSRFGuard</filter-name>
            <filter-class>org.owasp.csrfguard.CsrfGuardFilter</filter-class>
        </filter>
        <filter-mapping>
            <filter-name>CSRFGuard</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
  3.  Configure the Owasp.CsrfGuard.properties file as you see fit. org.owasp.csrfguard.Logger=org.owasp.csrfguard.log.ConsoleLogger
    org.owasp.csrfguard.NewTokenLandingPage=/login.jsp
    org.owasp.csrfguard.TokenPerPage=true
    org.owasp.csrfguard.TokenPerPagePrecreate=false

    org.owasp.csrfguard.Ajax=true

    org.owasp.csrfguard.action.Log=org.owasp.csrfguard.action.Log
    org.owasp.csrfguard.action.Log.Message=potential cross-site request forgery (CSRF) attack thwarted (user:%user%, ip:%remote_ip%, uri:%request_uri%, error:%exception_message%)

    org.owasp.csrfguard.unprotected.Public=/login.jsp
    org.owasp.csrfguard.unprotected.Public=/public/*

    org.owasp.csrfguard.TokenName=OWASP_CSRFTOKEN
    org.owasp.csrfguard.SessionKey=OWASP_CSRFTOKEN
    org.owasp.csrfguard.TokenLength=128
    org.owasp.csrfguard.PRNG=SHA1PRNG
NOTE: There are more configuration options that are available with CSRFGurard, please refer to configuration section for more details and detailed explanation of above properties.

References:
[1] - Cross-Site Request Forgery (CSRF)
[2] - 2011 Data Breach Investigation Report Verizon
[3] - OWASP CSRFGuard Project
[4] - CSRFGuard 3 User Manual

Wednesday, May 25, 2011

Using AJAX with Spring MVC 3.x

While working with one of my application, I had a simple requirement to grab customer data as they key-in their customer Id. First thought which came to my mind was to simply use AJAX however in the past we had to write lot of stuff and workarounds to make it work.

However, Spring 3.0 now officially support AJAX remoting with JSON as discussed in Keith Donald's article.

So, after reading this article the first step was to get jQuery and JSON javascript files which can be downloaded from their sites. This was easy!

Next, write the javascript code in the JSP page which activates on users input (to be specific on key up event). Here is how I did it:

First I veified that jQuery actually works on my page after adding following lines:
<script type="text/javascript" src="/travel-request/resources/js/jquery-1.4.min.js"></script>
<script type="text/javascript" src="/travel-request/resources/js/json.min.js"></script>
<script type="text/javascript">   
     $(document).ready(function() {
        console.log("Welcome to jQuery.");
      });
</script>

With the help of Firebug in FireFox I was able to verify using jQuery logging facility that it works!

So, half the job was done. Now comes the interesting part i.e. making an AJAX call to my customer information service and getting the response. Here is what I did:

Capture key up event and ignore any characters other than numbers i.e. 0-9
    $('#customerId').keyup(function(event) {
        var val = $(this).val();
        var regex = /[a-zA-Z\!@#%&()+{}?*+.^$ ]/g;
        if(val.match(regex)) {
            val = val.replace(regex, "");
            $(this).val(val);
        }
        if($('#customerId').val().length > 9 || $('#customerId').val().length == 8)
            clearCustomerData();
        else if ($('#customerId').val().length == 9) {
            userid_length = $('#customerId').val().length;   
            if (userid_length > 9){
                console.log('customer Id must be 9 numbers only...')
            }else
                {
                    getCustomerData();
                }
        }
    });


Next define implementation for getCustomerData() and clearCustomerData() functions which makes an AJAX call:
function getCustomerData() {
   $.getJSON("/customer/getInfo", { customerId: $('#customerId').val() }, function(customerAvailable) {
   if(customerAvailable.available) {
      $('#customerFirstName').val("customerAvailable.firstName");
      $('#customerMiddleName').val("customerAvailable.middleName");
      $('#customerLastName').val("customerAvailable.lastName");
   });
}

function clearCustomerData(){
   $('#customerFirstName').val("");
   $('#customerMiddleName').val("");
   $('#customerLastName').val("");

}
NOTE: $('#customerFirstName') above is linking the html label in the form.

At last, write a service using Spring magic which takes care of the rest as follows in your controller:
    @RequestMapping(value="/customer/getInfo", method=RequestMethod.GET)
    public @ResponseBody CustomerAvailable getCustomerName(@RequestParam String customerId){
        CustomerAvailable customer = new CustomerAvailable();
        customer.setAvailable(true);
        Map<String,String> customerData = new HashMap<String,String>();
        customerData.put("firstName", "FIRSTNAME");
        customerData.put("middleName", "M");
        customerData.put("lastName", "LASTNAME");
        return customer;
    }

Done! But, before I go don't forget to take a look at JSON formatter this is a nice tool to format unstructured JSON response and make it readable. I've added a link to this tool in references.

References:
https://src.springframework.org/svn/spring-samples/mvc-ajax/
http://blog.springsource.com/2010/01/25/ajax-simplifications-in-spring-3-0/
http://api.jquery.com/jQuery.getJSON/
http://ajaxian.com/archives/jquery-logging
http://stackoverflow.com/questions/3403574/no-results-message-on-jquery-autocomplete
http://stackoverflow.com/questions/2866108/jquery-keyup-illegal-characters
http://jetlogs.org/2007/09/14/jquery-textbox-validation-and-the-blur-event/
http://jsonformatter.curiousconcept.com/

Tuesday, May 24, 2011

Binding Boolean properties in Spring MVC forms

While designing Spring MVC forms you might often encounter bind errors such as follows:

Failed to convert property value of type [java.lang.String] to required type [java.util.Date] for property 'updateStamp'; nested exception is java.lang.IllegalArgumentException:xxxxxx

Usually these errors are the result of Spring not being able to bind java primitive Wrapper classes like Integer, Boolean, etc. or user defined types such as Customer, to <form:input> or other form fields.

However, this issue can be resolved simply by registering custom property editors with your spring controller. Spring by defaults provides you with set of built-in property editors, that you can use in your controller. For user defined types, you must create your own.

As you know, Spring 3.x makes writing your controller a lot easier and here is how you register customer property editor within your controller:

In the example below, I've added built in property editors for Date, String, and Boolean.
    @InitBinder
    public void setPropertyBinder(WebDataBinder dataBinder) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("MM-dd-yyyy");
        dateFormat.setLenient(false);
        dataBinder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false));
        dataBinder.registerCustomEditor(String.class, new StringTrimmerEditor(true));
        dataBinder.registerCustomEditor(Boolean.class, new CustomBooleanEditor(false));
    }

One important note: In some cases specifically for Boolean properties you may encounter following error even after you have registered custom property editor for it.

org.springframework.beans.NotReadablePropertyException: Invalid property 'newCustomer' of bean class [org.sample.domain.customer.Customer]: Bean property 'newCustomer' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?

This error is coming from your Customer domain object. Most likely, newCustomer property is defined as follows:
public class Customer {
    private Boolean newCustomer;

    public Boolean getNewCustomer() {
        return newCustomer;
    }

    public void isNewCustomer(Boolean newCustomer) {
        this.newCustomer = newCustomer;
    }
   
}

If you change the method name from isNewCustomer() to getNewCustomer() the above mentioned error will disappear. This is because a standard java bean convention is to use set/get for property methods.

Thursday, May 19, 2011

Securing Java Applications with Spring Security

Since there are so many post dedicated to the subject of this post. I will be collecting the articles and posting here as and when I come across them.

Java Web Application Security - Part I: Java EE 6 Login Demo

Java Web Application Security - Part II: Spring Security Login Demo

Friday, April 29, 2011

Using SQL IN clause with Prepared Statement

Using IN clause in prepared statements is not straight forward fortunately, there is a hack available for this scenario.

Example: Get list of customers who are in east cost states.
SQL could be: SELECT * FROM CUSTOMERS WHERE CUST_STATUS='ACTIVE' AND STATE IN('NJ','NY','MA','NH')

prepared statement - "SELECT * FROM  CUSTOMERS WHERE CUST_STATUS=? AND STATE IN (LIST_STATES)"

List queryForList = jdbcTemplate.queryForList(
    StringUtils.replace(sqlString, "LIST_STATES",
    ("'"+ StringUtils.replace(functions,",", "','") + "'")),new Object[] {});

Tuesday, April 26, 2011

Configuring Tomcat to Use JNDI based Oracle Datasource

In this post, I will talk about configuring a JNDI based datasource (Oracle) on Tomcat server which is a common way to access your backend.

1. Copy required Oracle driver jar files to $CATALINA_HOME/common/lib

2. Define your data source in Context $CATALINA_HOME/conf/server.xml
 
<!-- Global JNDI resources -->
  <GlobalNamingResources>
      <Resource name="jdbc/myoracle" auth="Container"
              type="javax.sql.DataSource" 
driverClassName="oracle.jdbc.OracleDriver"
              url="jdbc:oracle:thin:@127.0.0.1:1521:mysid"
              username="scott" password="tiger" maxActive="20" 
maxIdle="10" maxWait="-1"/> 

  </GlobalNamingResources> 

3. Add data source resource link in $CATALINA_HOME/conf/context.xml

<Context>
<Resource global="jdbc/myoracle" name="jdbc/myoracle" 
type="javax.sql.DataSource"/>
</Context>
 
That's it, now you are ready to use data source configured above 
from your application deployed on tomcat.