CodeIgniter Part 3: Secure Form Handling with message notifications using user registration form

in utopian-io •  6 years ago  (edited)

mrobele-ci-secure-form-handling-with-message-notifications-using2.jpg

Repository

CodeIgniter Github Repository

What will I learn?

  • How to build secure forms using codeIgniter form helper methods
  • How to validate form data appropriately before sending to the database
  • How to display notification messages to users on actions performed on a form or on a view.

Requirements

  • A good knowledge of PHP OOP programming
  • Understanding of HTML, CSS
  • Understanding of MVC flow pattern in CodeIgniter
  • Knowledge of database administration tools (I will be using phpMyAdmin in this tutorial for MySQL database administration).
  • A working server, local or live server to run the application
  • A good text editor of your choice for proper writing and formatting of your code ( I’m using visual studio code in this tutorial)
  • Previous tutorial

Difficulty

intermediate

Tutorial Contents

1. Building secure forms using codeigniter form helper methods:
Here we will be building the registration form using the codeigniter form helper methods, these will include adding the form attributes such as the method, action, and others if required, all this will be achieved in the register view.

2. Validating form data appropriately before sending to the database:
In this section once the form has been completed we will have to validate whatever information the user will be sending to our database in course of his registration to ensure that the data is clean and safe from treat to our system. This will be achieved through the Register Controller. and Users model

3. Displaying notification messages to users on actions performed on a form or on a view:
This will be used to illustrate how to properly display notification messages to the user based on the data filled on the form it can be success or error, it’s important for the user to know the result of each action. This interaction will take place between the model, controller and view if data is required from database or direct interaction between the controller and view.

Building secure forms using codeIgniter form helper methods

Before we start building the form, lets see how the form will look.
mrobele-ci-form-register.jpg

The above form was built using the codeIgniter form helper methods and the design was achieved using css and bootstrap, but in order for you to be able to fully utilize the codeIgniter form helper methods you must first auto load the form helper in the config file as shown in the figure below:
mrobele-autoload-form-helpers.jpg
We’ve already auto loaded these in the previous tutorial were we used a sign up and login form but I didn’t go into details of what we really did with these helpers, Let’s take a look at the code behind our form so you can get a clearer understanding of it. Head to your views folder and create a new file called register.php and add the following code:

<div class="well">
   <h1>Register</h1>
   <p>Please fill out the form below to create an account</p>
   (html comment removed: Display Error)
   <?php $attributes = array('id' => 'login_form','class'=> 'form-horizontal','role'=>'form');?>
   <?php echo form_open('Users/createUser',$attributes); ?>
   (html comment removed: field: Username)
   <p>
      <?php echo form_label('Name:'); ?>
      <?php
         $data = array(
            'name'  => 'Name',
            'value' => set_value('name'),
            'class' => 'form-control'
            );
         
            ?>
      <?php echo form_input($data); ?>
   </p>
   (html comment removed: field: Gender)
   <p>
      <?php echo form_label('Gender:');?>
      <?php 
         $options = array(
            'select'  => 'Select Gender',
                 'male'    => 'Male',
                 'female'    => 'Female'     
                );
              ?>
      <?php echo form_dropdown('gender', $options,'select'); ?>
   </p>
   (html comment removed: field: Username)
   <p>
      <?php echo form_label('Username:'); ?>
      <?php
         $data = array(
            'name'  => 'username',
            'value' => set_value('username'),
            'class' => 'form-control'
            );
         
            ?>
      <?php echo form_input($data); ?>
   </p>
   (html comment removed: field: Password)
   <p>
      <?php echo form_label('Password:'); ?>
      <?php
         $data = array(
            'name'  => 'password',
            'value' => set_value('password'),
            'class' => 'form-control'
            );
         
            ?>
      <?php echo form_password($data); ?>
   </p>
   (html comment removed: field: Confirm Password)
   <p>
      <?php echo form_label('Confirm Password:'); ?>
      <?php
         $data = array(
            'name'  => 'password2',
            'value' => set_value('password'),
            'class' => 'form-control'
            );
         
            ?>
      <?php echo form_password($data); ?>
   </p>
   (html comment removed: field: Submit Buttons)
   <p class="submit-button-box">
      <?php
         $data = array(
            'name'  => 'submit',
            'value' => 'Submit',
            'class' => 'btn btn-primary'
            );
         
            ?>
      <?php echo form_submit($data); ?>
   </p>
   <?php echo form_close(); ?>
</div>

Let’s take it bit by bit so you can understand each component and why It’s been used.

The form attributes and hidden fields:

<?php $attributes = array('id' => 'login_form','class'=> 'form-horizontal','role'=>'form');?>

This part of the code helps you to set the various attributes required by the form, as you can see we’ve been able to specify both an id and a class which we might need for javaScript functionality and css styling, the role attribute is not really a requirement for the form to function but I like using it as it adds to ease of accessibility of the form on the web. The attributes is also were you can specify enctype(encryption type) perhaps the form will require sending files to the database, like uploading pictures, here is an example of how it will look.

<?php $attributes = array('id' => 'login_form','class'=> 'form-horizontal','enctype'=>'multipart/form-data','role'=>'form');?>

Another parameter that can be set is if you need to add hidden fields to your form, we haven’t used this in our form as we don’t need it now but we might need it later on as we progress to more advanced concepts in this tutorial series, notwithstanding let me show you an example of how it can be set.

<?php $hidden = array('username' => 'obele', 'user_id' => '123');?>

Once all our required form properties have been set, we can then initialize the form using the form_open() method.

Form_open():
This is the method used to initialize the form, it has three parameters as argument these are;
$action: this is a string specifying the target url of the form
$attributes: usually an array of the form’s HTML attributes
$hidden: also an array of hidden fields as required in the form

The three parameters are not compulsory to all be present, from our registration form we only have the action and attributes as we don’t have any hidden fields. Here is our code for the form_open():

<?php echo form_open('Users/createUser',$attributes); ?>

You might be wondering why use this method instead of our traditional html form approach, well here is why,

  • It makes your site to be quite portable in case your urls ever change, the form_open action method automatically fits in the base_url which we configured in the config file, which means at any point in time where your app is moved to a new environment, it will automatically pick the url addresses to match with your form processing functions addresses you don’t have to manually change this again.
  • It also eliminated special characters like quoted strings, which if you were to use the normal html form pattern you will have to use the html_escape function to avoid this.
  • This also helps in protecting against Cross-Site request forgery (CSRF) which has already been implemented in the codeIgniter form helper.
  • This also helps in maintaining standards, for instance if you need to make changes to your sites forms which requires a change across all forms you can just perform the change in the helper file and this will cut across each form.
  • And it also helps in code readability as you have the flexibility to set your form filed attributes in arrays.

The form fields:
As I’ve mentioned in the last point above the form fields are added using arrays this makes the code to be quite readable, let’s look at this using two of our form fields, I will include comments for better understanding of each section.

<p>
      <?php echo form_label('Name:'); ?> (html comment removed: Form label to be displayed on the view, this will also be used for validation )
      <?php
         $data = array(
                'name'  => 'name',// Name to be used in posting the value to our database
                'value' => set_value('name'), //same thing as writing value = "name" in pure html
                'class' => 'form-control' //assigning a class to this input, you can also asign id and other input properties
                );
                ?>
      <?php echo form_input($data); ?>
   </p>

   <p>
      <?php echo form_label('Gender:');?>
      <?php 
         $options = array(
                 'male'    => 'Male',//dropdown option
                 'female'    => 'Female' //dropdown option   
                );
              ?>
      <?php echo form_dropdown('gender', $options,set_value('gender')); ?> (html comment removed: initialize the gender options to be set on the select field )
   </p>

Each of the form fields has an array of properties and values, I have included the
The value which is at the right is the actual name to be used for our validation and posting to the database.
I’ve also included the dropdown field to enable you understand how to properly use select dropdowns too.
For the css used for this design, I will be including a link to the full project if you like the design. Feel free to design it the way you feel best, the main focus is for you to understand the form helper methods and their usefulness and fully utilize them.

Validating form data appropriately before sending to the database

we need to ensure that the data we are receiving from the user is real data and is clean from treats, we will do this in the Users controller which we already created in our previous lesson with two additional form fields as added from the register view, let’s get into the Users controller and set our form validation rules, If you are just joining this tutorial series all you need to do is create a controller called Users and continue with us as we add the following code in it.

<?php
   
   if (!defined('BASEPATH')) {
       exit('No direct script access allowed');
   }
   
   class Users extends CI_Controller
   {
   
    public function __Construct() {
           parent::__Construct();
       }
   
   
    public function createUser(){
        $this->form_validation->set_rules('name','Name','trim|required|max_length[20]|min_length[4]|xss_clean');
        $this->form_validation->set_rules('gender','Gender','trim|required|xss_clean');
        $this->form_validation->set_rules('username','Username','trim|required|max_length[20]|min_length[4]|xss_clean');
        $this->form_validation->set_rules('password','Password','trim|required|max_length[20]|min_length[4]|xss_clean');
        $this->form_validation->set_rules('password2','Confirm Password','trim|required|max_length[50]|min_length[4]|xss_clean|matches[password]');
   
        if($this->form_validation->run() == FALSE){
   
            $data['main_content'] = 'Users/register';
            $this->load->view('layouts/main',$data);
   
        } else {
            
                $postData = $this->input->post();
             $validate = $this->Authentication_model->validate_user($postData);
             $password = $this->input->post('password');
             $enc_password = md5($password);
             $name   = $this->input->post('name');
             $gender = $this->input->post('gender');
             $username = $this->input->post('username');
            
                $data = array(
            'name'      =>$name,     
            'gender'    =>$gender, 
                'username'  =>$username,
                'password'  => $enc_password
                );
   
                if ($validate) {
                    $this->session->set_flashdata('user_exist','A user with those credentials already exists kindly review and try again');
                redirect(base_url('Register'));
                }else{
                    if ($this->User_model->create_user($data)) {
   
                $this->session->set_flashdata('user_registration','You have been registered successfully');
                redirect(base_url('Home'));
            }
            else{
                $this->session->set_flashdata('user_registration_error','unable to save your details try again');
                redirect(base_url('Register'));
   
            }
              }
            
   
        }
    }
   
   }
   
   ?>

From the code above let’s focus on the form validation rules here:

$this->form_validation->set_rules('name','Name','trim|required|max_length[20]|min_length[4]|xss_clean');
        $this->form_validation->set_rules('gender','Gender','trim|required|xss_clean');
        $this->form_validation->set_rules('username','Username','trim|required|max_length[20]|min_length[4]|xss_clean');
        $this->form_validation->set_rules('password','Password','trim|required|max_length[20]|min_length[4]|xss_clean');
        $this->form_validation->set_rules('password2','Confirm Password','trim|required|max_length[50]|min_length[4]|xss_clean|matches[password]');

For each of the validation rules, it starts with this
$this->form_validation->set_rules
This function helps us to set our validation rules, for this to work you need to auto load the form_validation library, this is done in the autoload.php inside the config folder, previously we already autoloaded the database and session libraries. Let’s auto load this in our config folder as in the diagram below:
mrobele-autoload-form-validation-library.jpg

The parameters of this function are limited to the rules you what to set for each field with each separated with vertical bar, we have used quite a few here this is based on our form validation requirements. But as we move on in this series and start building on more advanced concepts we will need more arguments. For now let me explain each parameter using the field with the more validation rules, ie the confirm password field;

$this->form_validation->set_rules('password2','Confirm Password','trim|required|max_length[50]|min_length[4]|xss_clean|matches[password]

The parameters

password2: the name of the field, this will hold the post value. So if we need to check the content of this field we will use this name password2

Confirm Password: this must match with the label name created in the view for the form filed, this is the name that will be used to display the error message so the user will know that the message is for the confirm password field.
Trim: used to remove whitespaces from the beginning and end of the string incase it exists
Max_length[50]: specifies the maximum length allowed for this field, in this case it has specified 50 as the maximum allowed characters.
min_length[4]: specifies the minimum length allowed for this field, in this case it has specified 4 as the minimum allowed characters.
XSS_CLEAN: this is used to guard against cross site scripting attacks, it usually returns an xss_clean string. Using it here means we are directly applying this method on the form field post value, to use this helper function, we need to load the codeigniter security helper, I’ve already shown you were I auto loaded the form_validation helper where the security helper was also loaded, for clearer understanding here it is again.
mrobele-autoload-form-helpers.jpg

Now we are set to display the result of the form action to our users, it could be an error message from the form validation or from the database or a success message.

Displaying notification messages to users on actions performed on a form or on a view

After we’ve ensured that the data entered by our user is clean and safe, we can now prepare the message to be displayed to the user.

Firstly let’s display the errors messages set by default by codeIgniter using our form field names as we’ve specified in the form validation rules, were do we now display these messages in case of validation errors.
Let’s go to our register view and tell codeIgniter to display the error message on the same view so that the user can directly see what he is doing wrong and correct it.

Add the following code at the top of the registration form before starting the form

(html comment removed: Display Error)
   <?php echo validation_errors('<p class="alert alert-dismissable alert-danger">'); ?>

The validation_errors method allows us to display any errors encountered during the validation process, I’ve used the bootstrap classes alert, alert-dismisable and alert-danger to display the error in a formatted alert through this you an style the alert message to your choice of display.

Now that we’ve set this error message, if we submit the form without filling it this is what we will get.
required-fields.jpg

Secondly, let’s set notification messages in the controller, these will be of two types, the success message and the error message.

  • Success message:
    This message will be displayed to the user if the form submission is successful, to achieve this we will set the success message in the controller when all validations and interactions with the model are successful, then we will display this message on the home page since the user will be redirected to the home page.
  • Error message:
    This will be shown to the user upon submitting the form, if there are any error aside the normal validation rules we’ve set, it could be that the entered values already exist in the database or say due to network related problems. To achieve this we will set the error message in the controller and display it in the register view, this is to enable the user see what error he is getting.

let’s implement these two in our createUser method. inside the Users Controller

<?php
   if (!defined('BASEPATH')) {
       exit('No direct script access allowed');
   }
   
   class Users extends CI_Controller
   {
   
    public function __Construct() {
           parent::__Construct();
       }
   
   
    public function createUser(){
        $this->form_validation->set_rules('name','Name','trim|required|max_length[20]|min_length[4]|xss_clean');
        $this->form_validation->set_rules('gender','Gender','trim|required|xss_clean');
        $this->form_validation->set_rules('username','Username','trim|required|max_length[20]|min_length[4]|xss_clean');
        $this->form_validation->set_rules('password','Password','trim|required|max_length[20]|min_length[4]|xss_clean');
        $this->form_validation->set_rules('password2','Confirm Password','trim|required|max_length[50]|min_length[4]|xss_clean|matches[password]');
   
        if($this->form_validation->run() == FALSE){
   
            $data['main_content'] = 'Users/register';
            $this->load->view('layouts/main',$data);
   
        } else {
            
            $postData = $this->input->post();
             $validate = $this->Authentication_model->validate_user($postData);// used to check from the autentication_model if the user exist or not it will return true if user exists
             $password = $this->input->post('password');
             $enc_password = md5($password);
             $name   = $this->input->post('name');
             $gender = $this->input->post('gender');
             $username = $this->input->post('username');
            
                $data = array(
                'name'      =>$name,     
                'gender'    =>$gender, 
                'username'  =>$username,
                'password'  => $enc_password
                );
   
                if ($validate) {
                    $this->session->set_flashdata('user_exist','A user with those credentials already exists kindly review and try again');
                redirect(base_url('Register'));
                }else{
                    if ($this->User_model->create_user($data)) {
   
                $this->session->set_flashdata('user_registration','You have been registered successfully');
                redirect(base_url('Home'));
            }
            else{
                $this->session->set_flashdata('user_registration_error','unable to save your details try again');
                redirect(base_url('Register'));
   
            }
              }
            
   
        }
    }
   
   }
   
   ?>

This is the full controller code, I’ve set three messages apart from the validation error messages, let’s take a look at these three

  • The error message when the user already exists
if ($validate) {
 $this->session->set_flashdata('user_exist','A user with those credentials already exists kindly review and try again');
 redirect(base_url('Register'));
 }

From the above the $validate variable is used to check if the user exist or not by calling the **validate_user ** method of the authentication_model, this we’ve created earlier for now just focus on the message we are setting I will post a link for the full code of this tutorial. If the user exists we then set a message using the $this->session->set_flashdata() method, this method has two parameters. The message variable and the message itself, in our case the message variable is user_exist this what we will use to display the message in the location where the page will redirect to. As you can see from the above we redirected to the Register controller which will display the resister view.

Let’s go the register view and display the user_exist message.
Add the following code on the registration view just above the validation_error message

(html comment removed: Display user_exist Errors)
   <?php if($this->session->flashdata('user_exist')) : ?>
   <p class="alert alert-dismissable alert-danger text-center"><?php echo $this->session->flashdata('user_exist');?></p>
   <?php endif; ?>

The code above checks if the uer_exist error message was generated, if true then it will display it in an alert format for the user. With this if a user tries to fill same information twice it will display the error as below

mrobele-user-exists.jpg

This is the full controller code, I’ve set three messages apart from the validation error messages, let’s take a look at these three

  1. The error message when the user already exists
    if ($validate) {
    $this->session->set_flashdata('user_exist','A user with those credentials already exists kindly review and try again');
    redirect(base_url('Register'));
    }

From the above the $validate variable was used to check if the user exist or not by calling the validate_user method of the authentication model, this we’ve created earlier for now just focus on the message we are setting I will post a link for the full code of this tutorial. If the user exists we then set a message using the $this->session->set_flashdata() method, this method has two parameters. The message variable and the message itself, in our case the message variable is user_exist this what we will use to display the message in the location where the page will redirect to. As you can see from the above we redirected to the Register controller which will display the resister view.
Let’s go the register view and display the user_exist message.
Add the following code on the registration view just above the validation_error message
(html comment removed: Display user_exist Errors)

session->flashdata('user_exist')) :?>

session->flashdata('user_exist');?>

The code above checks if the uer_exist error message was generated, if true then it will display it in an alert format for the user. With this if a user tries to fill same information twice it will display the error as below

  • Success message to be displayed on the home page once the user’s submission is successful:
if ($this->User_model->create_user($data)) {
 $this->session->set_flashdata('registration_success','You have been registered successfully');
  redirect(base_url('Home'));
 }

From here the user has been successfully create by calling the create_user method of the User_model, so we set the registration_success message variable with it’s message and redirect the user to the home page. Let’s make this message available on the home page.

Place the below code at the top of the home page.

<?php if($this->session->flashdata('registration_success')) : ?>
<p class="alert alert-dismissable alert-success text-center"><?php echo $this->session->flashdata('registration_success');?></p>
<?php endif; ?>

This will display the registration_success message on the home page once the user’s registration is successful as shown below:
mrobele-ci-form-handling-homepage.jpg

  • Error message to be shown to the user for unknown errors arising:
    Let’s set this message in the controller.
else{
 $this->session->set_flashdata('user_registration_error','unable to save your details try again');
redirect(base_url('Register'));
  }

And finally make it visible on the registration page.

<div class="well">
   <?php if($this->session->flashdata('user_registration_error')) : ?>
   <p class="alert alert-dismissable alert-success text-center"><?php echo $this->session->flashdata('user_registration_error');?></p>

This brings us to the end of this part of the tutorial series, I will include a link for the full code of this tutorial covering all the controllers, models and views for your study, but feel free to ask were necessary.

Curriculum

Proof of work done

GitHub repository for this tutorial
https://github.com/MrObele/CI-Secure-form-handling-using-registration-form

Authors get paid when people like you upvote their post.
If you enjoyed what you read here, create your account today and start earning FREE STEEM!
Sort Order:  

Thank you for your contribution.
While I liked the content of your contribution, I would still like to extend few advices for your upcoming contributions:

  • Put more resources.
  • Don't do a very extensive tutorial, it is preferable to have parts.

Looking forward to your upcoming tutorials.

Your contribution has been evaluated according to Utopian policies and guidelines, as well as a predefined set of questions pertaining to the category.

To view those questions and the relevant answers related to your post, click here.


Need help? Write a ticket on https://support.utopian.io/.
Chat with us on Discord.
[utopian-moderator]

Thank you for your observations, these will be addressed in the coming tutorials

Congratulations @mrobele! You have completed some achievement on Steemit and have been rewarded with new badge(s) :

Award for the number of upvotes received

Click on any badge to view your Board of Honor.

To support your work, I also upvoted your post!
For more information about SteemitBoard, click here

If you no longer want to receive notifications, reply to this comment with the word STOP

Do you like SteemitBoard's project? Vote for its witness and get one more award!

I will love to commend you for keeping this series alive. I have gained a lot in these two major aspect

  • how to create algorithms that works
  • using code igniter to validate your forms

But moving forward, I will love to see more of this in your subsequent tutorials

  • More algorithm based structure to show communication between the languages

Thanks for your contribution. Looking forward to your next tutorial.

Hey @mrobele
Thanks for contributing on Utopian.
We’re already looking forward to your next contribution!

Contributing on Utopian
Learn how to contribute on our website or by watching this tutorial on Youtube.

Want to chat? Join us on Discord https://discord.gg/h52nFrV.

Vote for Utopian Witness!

You have a minor misspelling in the following sentence:

And finaly make it visible on the registration page.
It should be finally instead of finaly.

Thanks, updated