EIW Fall 2000 Lecture Notes - Hidden Fields


State Information and CGI programming

Each time a CGI program is run the only information available to the CGI program comes via the HTTP request. The CGI program has no way of knowing whether the request is from a user that has "entered" the system previously unless that information is part of the request.

Consider a Web-Based Pizza Ordering System:

The issue that we are concerned with is this: How does system will know what user is ordering a pizza when the second request is received?

There is no information in the second query that identifies the user, so thery is no way the system can tell who is ordering pizza! We've seen this before - remember when you had to go and change your grade in a student database by constructing a query string by hand? The problem with that system is that it assumed that if you knew what kind of query needed to be sent, you had permission to make changes. Here we have a different problem - we need to know where to send the pizza!

Using Hidden Fields

One solution to the previous problem is to use a hidden field in the order form. The hidden field identifies the user (or the session). For a user named "Hungry Student" we might use the following form:

<FORM ACTION=/cgi-bin/orderpizza.cgi METHOD=POST>

<INPUT TYPE=HIDDEN NAME=name VALUE="Hungry Student">

Type of Pizza: 
<INPUT TYPE=RADIO NAME=pizza VALUE=cheese>    Cheese 
<INPUT TYPE=RADIO NAME=pizza VALUE=veggie>    Veggie 
<INPUT TYPE=RADIO NAME=pizza VALUE=pepperoni> Pepperoni <P>

Pizza Size: 
<INPUT TYPE=RADIO NAME=size VALUE=large>      Large 
<INPUT TYPE=RADIO NAME=size VALUE=medium>     Medium 
<INPUT TYPE=RADIO NAME=size VALUE=small>      Small <BR>

<INPUT TYPE=SUBMIT>
</FORM>

Type of Pizza: Cheese Veggie Pepperoni

Pizza Size: Large Medium Small

And now the associated query string might look like this:

name=Hungry+Student&pizza=cheese&size=large

Now the CGI program orderpizza.cgi will get all the information it needs, including the identity of the person ordering pizza.

NOTE: It is important to realize that our system is not secure, anyone can look at the HTML source for our pizza order form and see that requests should include the field "name". If you know someone's login name you can order 1000 pizzas for them!

A hidden field based pizza serving is running at: cgi.cs.rpi.edu/~hollingd/eiw/CGI/pizza

Session Keys

Many Web based systems use hidden fields that identify a session instead of a user. A session includes a sequence of queries that are all somehow related (typically coming from the same user over a short span of time). In our case a session includes the login query and the subsequent order query.

A system that uses session keys requires some kind of database that is used to store session keys and provide the connection between the user and a session key. Here is the general idea:

  1. An initial login form is used and the user provides a name and password.
  2. The login CGI checks the name and password, and if everything checks out a session key is created. Session keys have the following properties:
  3. New forms sent back by the "system" (in our example a pizza order form) contain a hidden field with the session key as the value. This means that all CGI requests other than a login request must include a valid session key. Generating session keys that meet the properties mentioned above is not trival, although there are some well-known methods. Here is one simple method: Here is some perl code that will generate a session key using the above method - check any perl reference if you want more details on how to use the rand function.

    
    # perl subroutine to generate a session key
    # given a username. 
    # Example usage:
    #   $key = generate_sessionkey($name);
    
    sub generate_sessionkey {
        local($name) = $_[0];	# the user name
    
        # initialize the random number generator
        srand();
        
        # generate a sequence of 10 random digits
        local($randstring,$i);
        for ($i=0;$i<10;$i++) {
    	$randstring = $randstring . int(rand(10));
        }
        return $name . $randstring;
    }
    

    If we change our pizza server CGI to use a hidden field containing a session key instead of a user name and password, the system is much more secure. Now a pizza order form might look like this:

    <FORM ACTION=/cgi-bin/orderpizza.cgi METHOD=POST>
    
    <INPUT TYPE=HIDDEN NAME=sessionkey VALUE="Hungry Student9741189023">
    
    Type of Pizza: 
    <INPUT TYPE=RADIO NAME=pizza VALUE=cheese>    Cheese 
    <INPUT TYPE=RADIO NAME=pizza VALUE=veggie>    Veggie 
    <INPUT TYPE=RADIO NAME=pizza VALUE=pepperoni> Pepperoni <P>
    
    Pizza Size: 
    <INPUT TYPE=RADIO NAME=size VALUE=large>      Large 
    <INPUT TYPE=RADIO NAME=size VALUE=medium>     Medium 
    <INPUT TYPE=RADIO NAME=size VALUE=small>      Small <BR>
    
    <INPUT TYPE=SUBMIT>
    </FORM>
    

    Type of Pizza: Cheese Veggie Pepperoni

    Pizza Size: Large Medium Small

    And an order query string might look like this:

    sessionkey=Hungry+Student9741189023&pizza=cheese&size=large
    

    There is a sessionkey based pizza server running at: cgi.cs.rpi.edu/~hollingd/eiw/CGI/pizzasession