Saturday, August 30, 2014

How To Create Your Own JQuery Plugin



1. Introduction

JQuery is very popular library which allows you to manipulate DOM easily. It also has lots of plugins. Creating your own plugin seem a bit hard first. However, it's not that much hard. Let us see how to create a simple JQuery plugin.


2. Problem Statement


By default, when you create hyperlink in html, it has underline and has text with blue color. Let us try to convert all hyperlink elements to red color without underline. With basic JQuery you can do like this :


$('a').css('text-decoration','underline')  
$('a').css('color','blue')
Let us create our own JQuery plugin to do above task.


3.  JQuery plugin structure :

(function($){

        $.fn.myFunction = function(){

        }

}(JQuery))


Let's take a quick look to understand above code template. We are defining here anonymous Javascript function i.e. function without name. We are also calling this anonymous function right there with only one parameter i.e. JQuery. By including our functionality in this self-enclosed anonymous function, we are eradicating chances of collision with other Javascript variables/functions.

With $.fn you can define your own JQuery plugin which will be accessible with $ variable later.


4. Simple plugin definition :


Let us define our own convertToMyLink function.


(function($){

       $.fn.convertToMyLink = function(){

               this.css('color','red');

               this.css('text-decoration','none');         

       }

}(JQuery))



With this, now you can call your own function like as follows :

$('a').convertToMyLink();


5. Chaining :

Most of the JQuery plugins support chaining of functions. For example, $('a').css('color','red').text();

With our current definition chaining won't work. To support that just update the function definition like this :

(function($){

       $.fn.convertToMyLink = function(){

               this.css('color','red');

               this.css('text-decoration','none');

               return this;         

       }

}(JQuery)) 



6. Accepting options for your function :

Let us provide text color & background color as a option to our function. If color is not provided we will use default one.


(function($){

       $.fn.convertToMyLink = function(userOptions){

       // If userOptions are not provided use following default ones

       var options = $.extend({

                color : 'red',

                backgroundColor : 'white'

       }, userOptions);       



       return this.css({

               color : options.color,

               backgroundColor : options.backgroundColor

       });

}(JQuery))




Example usage :

$("a").convertToMyLink({color : 'green'});
Custom JQuery plugins are very good option when you want to convert you repetitive task into one module. 
Thanks for reading.

Thursday, July 31, 2014

Cook your project infrastructure with Chef & Vagrant


Introduction

A good engineer can meticulously design a great infrastructure. However, what if you ask him to design the same thing multiple times. Well, it's a hell lot of boring & tedious task. Also, it will make the next iteration error prone. Now, here comes, smart engineering by automating the infrastructure. Let's learn to do it using chef and vagrant. I will try not to make this post too much theoretical as there are lots of information out there on web. So, let's start cooking !!!

Brief Intro of Chef and Vagrant

Chef is a open source infrastructure automation framework. Using this framework you can build your whole infrastructure. It can represent your infrastructure as code. Now, what is vargant, imagine you created some code using chef to build your infrastructure. To test your code, you will either need a machine or a VM. Suppose unfortunately your code fails. You will again need a new machine/VM or you will format the older one and you will try again. Seems uninteresting right ? Here comes vagrant to rescue you from these issues. Vagrant is a tool to create, configure and manage virtual environments easily. With the vagrant boxes you can test your chef code easily. Now, enough of theory, let's do some practical stuff.

Installing chef and vagrant

1. Install virtualbox to install VMs. You can download it  from the site https://www.virtualbox.org/wiki/Downloads

2. Install vagrant. You can download it from the site http://www.vagrantup.com/downloads.html

3. Install git.


Key Components of chef framework :

Some key components of chef which you should know before proceeding further. There are many important components but will focus only on two.

Cookbook : Cookbook is a collection of recipes which tells chef how to install something. Cookbooks to install apache, tomcat, mysql are already there. These cookbooks are very well written which also take care of underlying OS while installing. There are lots of other cookbooks, you can get those from http://community.opscode.com/cookbooks
You can also create you own cookbooks.

Recipe : It's just a ruby file containing bunch of ruby functions to do certain tasks (installation, configuration)

Now, let's try to install Apache for our demo app using chef. First let us set up the environment for this process.

Setting up environment :

1. Download chef-repo from git.


2.  Go into chef-repo directory and create a new directory .chef there. Inside .chef directory create a file called knife.rb. Add following line in knife.rb :

       cookbook_path ['../cookbooks']

Above line will configure knife with chef framework and will tell knife where cookbooks are stored.
You will have to provide the path of cookbooks which in this case inside chef-repo directory.

3. Run command : 

      knife cookbook create myapp

This will create you own cookbook with name myapp. This will also have all the directories to define other chef components.


myapp directory structure will look like 


.
|-- attributes
|-- CHANGELOG.md
|-- definitions
|-- files
|   `-- default
|-- libraries
|-- metadata.rb
|-- providers
|-- README.md
|-- recipes
|   `-- default.rb
|-- resources
`-- templates
    `-- default




Adding Apache cookbook and configuring with chef :

1. Go to 'myapp' directory and run following command  : 

       knife cookbook site install apache2

This will download already created cookbook apache2. This will also download dependencies for apache, if any.

2. Open default.rb file inside myapp/recipes directory. This is the first file which will get executed by chef.

3. Add following snippet of code in default.rb file:

include_recipe "apache2"
apache_site "default" do
  enable true
end

As we discussed, cookbook can have various recipes. We are including desired ones in our own cookbook. So, at first line we are including apache2 recipe which comes with apache2 cookbook. On the next line, we are setting value of apache_site attribute to true. This will add a demo html file in apache document root directory. There could be various attributes which you can customize like server timeout, listening_port. You can check more configuration options on site https://github.com/onehealth-cookbooks/apache2.

Configuring vagrant to test your chef project :

1. Let's add vagrant base box to test our chef code. This box will act as a separate new machine for us. We don't have to go through any OS installation steps. You can think of it as a ready to use machine.


               vagrant add MyCentOSBox http://www.lyricalsoftware.com/downloads/centos65.box

Above command will add a vagrant box with Cent-OS from given url and vagrant will identify it with name MyCentOSBox. You can also choose any other type of box from http://www.vagrantbox.es/.

Above command will also place a Vagrantfile in the current directory. This file will have following code which tells vagrant which is the default box.
         Vagrant.configure("2") do |config|
                 config.vm.box = "MyCentOSBox"
                 config.vm.box_url = "http://www.lyricalsoftware.com/downloads/centos65.box"
         end

2. To integrate chef with Vagrant for provisioning, open Vagrantfile and add following code.
          Vagrant.configure("2") do |config|
                  config.vm.box = "MyCentOSBox"
                  config.vm.box_url = "http://www.lyricalsoftware.com/downloads/centos65.box"
                 config.vm.provision :chef_solo do |chef|
                        chef.cookbooks_path = "~/chef-repo/cookbooks/"
                        chef.add_recipe "myapp"
                 end
           end
Above code will configured chef solo with vagrant. We are also providing cookbook path and recipe name which we want to execute by vagrant.

Running chef scripts through vagrant

1. Add port forwarding :

Apache will be install inside virtual machine, so we need some way to test our site through browser. Vagrant allows you to map a port on the your machine i.e. host machine to a port on the virtual machine, by forwarding all the traffic. So, let’s map port 8888 on localhost to port 80 on the virtual machine. You will just have to add following one line inside config code in Vagrantfile.

         Vagrant.configure("2") do |config|
               config.vm.box = "MyCentOSBox"
               config.vm.box_url = "http://www.lyricalsoftware.com/downloads/centos65.box
               config.vm.network :forwarded_port, guest: 80, host: 8888
               config.vm.provision :chef_solo do |chef|
                    chef.cookbooks_path = "~/chef-repo/cookbooks/"
                    chef.add_recipe "myapp"
                end
         end

2. Now, we are all set to run our chef script through vagrant. Just run the following command. This will boot the vm and also do the provisioning.

vagrant up

If you have already booted vm and just want to re-provision chef. Just run the following command.

vagrant provision


Now you can open http://localhost:8888/ on your machine's browser and you will see apache's default page.


3. To shutdown vm just run command
 
vagrant halt


4. To try again from scratch :

Just run following command :


vagrant destroy 

and followed by command :


vagrant up

You can also login to vm using :


vagrant ssh



Thanks for reading. I hope, using this blog, you will be able to automate your project infrastructure. I would appreciate your comments and suggestions, if any.

Monday, March 19, 2012

Rescue the Session Fixation Problem in Java with Apache Tomcat Valves


1. Introduction 

Session Fixation is a web application vulnerability found in many web-based applications which uses same session identifier (session ID) after login. This allows the attacker to exploit the vulnerability by setting another user's session ID. To avoid this, we must create a new session after successful authentication.

2. How to do it in JAVA ?  

Basically, after successful authentication, we have to invalidate the current session and create a new one.
Following is the code snippet to do the same.



     // request is of type HTTPServletRequest
     HttpSession session = request.getSession(); 
     session.invalidate();
     request.getSession(true);
       
 

getSession() method gives the current session object. To create a new session call the same method with 'true' parameter. Passing 'false' to the method is same as calling method with no parameters.

3. Problem with above approach :

Above logic will work only if the session is created over HTTP. But, it won't work if the session is created over HTTPS. To represent the HTTPS session there is a different class SSLSession. I tried various things and also searched on Google but I had no luck. Finally, I came to know about Tomcat Valves.

4. What is Tomcat Valve ?

Tomcat Valves are special filters which intercepts all request before they get processed. Some of you may be familiar with servlet filters used by web applications to do application-specific processing of the request. The key distinction between servlet filters and Tomcat Valves is that Valves are applied and controlled through the configuration of the application server. Depending on the container definition where the Valve element appears in the Tomcat configuration, the valve could be configured for all applications on the application server, a subset of applications, or even a single application. Apache Tomcat comes with a number of valves, including AccessLogValve, RemoteAddressFilter, SingleSignOnValve, and others.

You can also create your own valve by 2 ways :
a. Extending ValueBase class
b. Implementing Value interface.

If you are going with second way you have to implement some other unnecessary methods also. So, I would prefer the first one. In the first one you just need to override the invoke method.

5. Tomcat Valve Example to resolve the Session Fixation problem :

Here is the example of SessionFixationValve which I have used.





package org.tomcat.valves.sessionFixation;

import java.io.IOException;
import javax.servlet.ServletException;
import org.apache.catalina.Session;
import org.apache.catalina.authenticator.Constants;
import org.apache.catalina.authenticator.SavedRequest;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.catalina.valves.ValveBase;

public class sessionFixationValve extends ValveBase{
 
 private String authenticationUrl = "/j_acegi_security_check";
 
 public void setAuthenticationUrl(String authenticationUrl) {
  
  if(authenticationUrl.equals("")){
     throw new IllegalArgumentException("String is empty.");   
  }
  this.authenticationUrl = authenticationUrl;
 }

 @Override 
 public void invoke(Request req, Response response) throws IOException,
   ServletException {  
  // check for the login URI, only after a login
  // we want to renew the session  
  if (req.getRequestURI().contains(authenticationUrl)) {

     // save old session
    Session oldSession = req.getSessionInternal(true);
    SavedRequest saved = (SavedRequest) oldSession.
     getNote(Constants.FORM_REQUEST_NOTE);

    // invalidate old session
    req.getSession(true).invalidate();
    req.setRequestedSessionId(null);
    req.clearCookies();

    // create a new session and set it to the request
    Session newSession = req.getSessionInternal(true);
    req.setRequestedSessionId(newSession.getId());

    // copy data from the old session
    // to the new one
    if (saved != null) {
      newSession.setNote(Constants.FORM_REQUEST_NOTE, saved);
    }   
    
  } 
  // after processing the request forward it
  getNext().invoke(req, response);
 }

}



6. Installing the Valve :

To make the Valve work, use following steps :

1. Create a jar for above code and put it in the $TOMCAT_HOME/server/lib/.
2. Declare valve in the server.xml. Put it under the Host node.
3. Set the authenticationUrl value as per your web application.




<Host>
  <Valve className="org.tomcat.valves.sessionFixation.sessionFixationValve" authenticationUrl="/j_acegi_security_check"/>
</Host>



7. Reference:

This solution was devloped by Daniel Wasser and Thomas Schmidt.

Get the more information about Tomcat API's here.