CodeIgniter Forums

Full Version: I just created this "form key" library, need suggestions
You're currently viewing a stripped down version of our content. View the full version with proper formatting.

El Forum

[eluser]IamPrototype[/eluser]
From this tutorial (http://net.tutsplus.com/tutorials/php/se...form-keys/) I just re-wrote the content and coded it into a CI library.

Here's the library and a testing controller with two testing views.

----

library (last updated: 18. juni 09 23:03 - 24-hour system)
Code:
<?php

#doc
#    classname:    Form_Key
#    note:        Prevents other sites from sending post data to forms on your site
#/doc

class Form_Key
{
    #    internal variables
    private $form_key;
    private $old_form_key;
    private $ci;
    
    #    __construct
    function __construct()
    {
        // Load additional libraries
        $this->load->library('session');
        // Get instance
        $this->ci =& get_instance();
        
        // Checks if the session form_key is set, if true, assign the session's value to our old_form_key variable
        if (isset($this->ci->session->userdata('form_key'))
        {
            $this->old_form_key = $this->ci->session->userdata('form_key');
        }
    }
    ###
    
    #    generate_key
    function _generate_key()
    {
        $ip = $_SERVER['REMOTE_ADDR']; // User's IP address
        $uniqid = uniqid(mt_rand(), TRUE); // Generates a random key
        return sha1($ip.uniqid); // Return the newly generated key
    }
    ###    
    
    #    output_key
    function output_key()
    {
        $this->form_key = $this->generate_key(); // Generates a unqiue key using our _generate_key method
        $this->ci->session->set_userdata('form_key', $this->form_key); // Sets a new session called form_key with our new unique key
        echo '<input type="hidden" name="form_key" id="form_key" value="'.$this->form_key.'" />'; // Simple input with our key as the value (hidden)
    }
    ###
    
    #    validate
    function validate()
    {
        return $this->input->post('form_key') == $this->old_form_key;
    }
    ###

}
###

### end of library

testing controller
Code:
<?php

#doc
#    classname:    Formkey
#    scope:        Public
#
#/doc

class Formkey extends Controller
{
    #    __construct
    function __construct()
    {
        parent::Controller();
        
        // Load additional libraries
        $this->load->library('formkey');
    }
    ###    
    
    #    index
    function index()
    {
        $this->form();
    }
    ###
    
    #    form
    function form()
    {
        $data['form_key'] $this->formkey->output_key();
        $this->load->view('test_view', $data);
    }
    ###
    
    #    validateform
    function validateform()
    {
        if ($this->formkey->validate())
        {
            // Success! Go on with validation (e.g. form_validation)
            
            // If this method of doing it is bad practice, would it be any better
            // to make the variable old_form_key public in the library
            // and apply the session's value to a var in this validateform method
            // and then use the form_validation class for the final validate?
            // Please, any suggestions!
        }
        else
        {
            $data['err_msg'] = "Key is invalid!"; // Redirect user back to the form view and display error message
            $this->load->view('test_fail_view', $data);
        }
    }
    ###

}
###

### end of controller

first testing view (form)
Code:
<html >
<head>
    <title>Making our forms secure using form keys!</title>
    <meta http-equiv="Content-type" content="text/html; charset=UTF-8" />
    <meta name="description" content="apple juice addict" />
</head>
<body>
    <form method="post" action="formkey/validate" id="test_form" name="test_form">
        <?=$form_key?>
        <label for="email">Email</label> &lt;input type="text" name="email" id="email" /&gt;&lt;br />
        <label for="website">Website</label> &lt;input type="text" name="website" id="website" /&gt;&lt;br />
        &lt;input type="submit" name="submit" id="submit" value="Submit!" /&gt;
    &lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;

second testing view (fail)
Code:
&lt;html &gt;
&lt;head&gt;
    &lt;title&gt;Making our forms secure using form keys!&lt;/title&gt;
    &lt;meta http-equiv="Content-type" content="text/html; charset=UTF-8" /&gt;
    &lt;meta name="description" content="apple juice addict" /&gt;
&lt;/head&gt;
&lt;body&gt;
    <p>&lt;?=$err_msg?&gt;</p>
&lt;/body&gt;
&lt;/html&gt;

-----

I actually just wrote it, so I guess there could be some problems, typos and so on.. any suggestions would be nice! I want to optimize the code as much as I can.

PS: Would a library like this make sense for you? Or would you just use the already made cURL libraries?

Edit: Typo, library update

El Forum

[eluser]Dam1an[/eluser]
I actually had this bookmarked to go over at some point lol

I just quickly glossed over the code, and 2 things jumped out
1) CamelCase class name for the library, tut tut, should use underscores as per the style guide
2) You could rewrite the validate function in one line
Code:
// From this
if ($this->input->post('form_key') == $this->old_form_key)
{
    return TRUE; //  The key is valid, return true
}
else
{
    return FALSE; // The key is invalid, return false
}

// To this
return $this->input->post('form_key') == $this->old_form_key;

Edit: I'll probably give some more in depth comments when I actually read the article

El Forum

[eluser]IamPrototype[/eluser]
Thanks, I've edited my library. Smile

El Forum

[eluser]xwero[/eluser]
The tutorial creates a class for one thing; generating the form key. Just put the function in a helper/plugin and then in the controller you can add the key to the session and pass it to the view to create a hidden input. You can validate the key using a validation callback.

El Forum

[eluser]IamPrototype[/eluser]
Ah, good stuff. I realize it's so simple that a helper would fit much better. Thanks.

Btw, you're saying I shouldn't create a output function for the hidden input, or? Just thought it would make it more simple and "easy-to-go". Smile

El Forum

[eluser]xwero[/eluser]
I think the output function as it is just limits you and the form helper already as a few ways to generate hidden input fields so why create another?

El Forum

[eluser]elvix[/eluser]
There's a couple of CSRF libraries floating around already (same concept, CSRF = cross-site request forgery). You might want to check those out.

One benefit is that they extend the input controller, and the form helper, adding the CSRF protection transparently to all your forms. There's also a token generator which is useful to get CSRF working with Ajax scripts.

El Forum

[eluser]IamPrototype[/eluser]
I didn't know that, thanks, I'll go check it out!

Edit: Seems that most plugins are out of date????