Friday, November 13, 2020

File Upload in PHP with jQuery AJAX

 Create a file index.php in your PHP project and copy and past the following code into your index.php file.

<!doctype html>
<html>
<head lang="en">
<meta charset="utf-8">
<title>Ajax File Upload with jQuery and PHP</title>
<link rel="stylesheet" href="style.css" type="text/css" />
<script type="text/javascript" src="js/jquery-1.11.3-jquery.min.js"></script>
<script type="text/javascript" src="js/script.js"></script>

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
</head>
<body>
<div class="container">
<div class="row">

<div class="col-md-8">

<h1><a href="#" target="_blank"><img src="logo.png" width="80px"/>Ajax File Uploading with Database MySql</a></h1>
<hr> 

<form id="form" action="ajaxupload.php" method="post" enctype="multipart/form-data">
<div class="form-group">
<label for="name">NAME</label>
<input type="text" class="form-control" id="name" name="name" placeholder="Enter name" required />
</div>
<div class="form-group">
<label for="email">EMAIL</label>
<input type="email" class="form-control" id="email" name="email" placeholder="Enter email" required />
</div>

<input id="uploadImage" type="file" accept="image/*" name="image" />
<div id="preview"><img src="filed.png" /></div><br>
<input class="btn btn-success" type="submit" value="Upload">
</form>

<div id="err"></div>
<hr>
<p><a href="https://www.cloudways.com" target="_blank">www.Cloudways.com</a></p>
</div>
</div>
</div></body></html>

Using jQuery & AJAX for File Upload Form

Since I will use jQuery & AJAX for submitting data and uploading the files, I will start by including the jQuery library first.

  1. <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>

$(document).ready(function (e) {
 $("#form").on('submit',(function(e) {
  e.preventDefault();
  $.ajax({
         url: "ajaxupload.php",
   type: "POST",
   data:  new FormData(this),
   contentType: false,
         cache: false,
   processData:false,
   beforeSend : function()
   {
    //$("#preview").fadeOut();
    $("#err").fadeOut();
   },
   success: function(data)
      {
    if(data=='invalid')
    {
     // invalid file format.
     $("#err").html("Invalid File !").fadeIn();
    }
    else
    {
     // view uploaded file.
     $("#preview").html(data).fadeIn();
     $("#form")[0].reset(); 
    }
      },
     error: function(e) 
      {
    $("#err").html(e).fadeIn();
      }          
    });
 }));
});

In the above code using the $ajax() method for sending data to php also check the success data or error in data sending.

Configure and Connect MySQL Database With PHP

The next step is setting up and configuring the MySQL database. Go to the Cloudways Database Manager and create a table named ‘uploading’. The fields of this table are name, email, file_name. Alternatively, you could use the following SQL query:

  1. CREATE TABLE `uploading` (
  2. `id` int(11) NOT NULL AUTO_INCREMENT,
  3. `name` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
  4. `email` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
  5. `file_name` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
  6. PRIMARY KEY (`id`)
  7. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

Next, create db.php to connect the database with the PHP application. Paste the following code snippet in the file:

  1. <?php
  2. //DB details
  3. $dbHost = 'localhost';
  4. $dbUsername = 'root';
  5. $dbPassword = '';
  6. $dbName = 'fileUploadDb';
  7. //Create connection and select DB
  8. $db = new mysqli($dbHost, $dbUsername, $dbPassword, $dbName);
  9. if($db->connect_error){
  10. die("Unable to connect database: " . $db->connect_error);
  11. }

Create a PHP Script for File Uploading

When the user interacts with this form, the file is uploaded to the temporary folder and all the information about the file is stored in the multidimensional array known as $_FILES.The Key Index of this array is the name attribute on this <input type=’’file’ name=”image” > field.

In this case, $_FILES[“image”] is the index name.more information about the file is stored in the following indexes.

  1. <?php
  2. $img = $_FILES["image"]["name"] stores the original filename from the client
  3. $tmp = $_FILES["image"]["tmp_name"] stores the name of the designated temporary file
  4. $errorimg = $_FILES["image"][“error”] stores any error code resulting from the transfer
  5. ?>

Once the file has been uploaded to the temporary folder and all its information saved in the array, the move_uploaded_file() function is used to move the file from its present temporary location to a permanent location. The process of uploading the file is as follows:

  1. Check if there are any errors in the upload.
  2. Check if the file type is allowed
  3. Check that the file is under the set file size limit
  4. Check if the filename is valid (if the filename has a /, it will affect the destination path).
  5. Check that the file doesn’t already exist at the target location (based on the name).
  6. Finally, upload the file.

Let’s create the PHP script to deal with the functionality of file uploading. Create ajaxupload.php and type the following code in it.

  1. <?php
  2. $valid_extensions = array('jpeg', 'jpg', 'png', 'gif', 'bmp' , 'pdf' , 'doc' , 'ppt'); // valid extensions
  3. $path = 'uploads/'; // upload directory
  4. if(!empty($_POST['name']) || !empty($_POST['email']) || $_FILES['image'])
  5. {
  6. $img = $_FILES['image']['name'];
  7. $tmp = $_FILES['image']['tmp_name'];
  8. // get uploaded file's extension
  9. $ext = strtolower(pathinfo($img, PATHINFO_EXTENSION));
  10. // can upload same image using rand function
  11. $final_image = rand(1000,1000000).$img;
  12. // check's valid format
  13. if(in_array($ext, $valid_extensions))
  14. {
  15. $path = $path.strtolower($final_image);
  16. if(move_uploaded_file($tmp,$path))
  17. {
  18. echo "<img src='$path' />";
  19. $name = $_POST['name'];
  20. $email = $_POST['email'];
  21. //include database configuration file
  22. include_once 'db.php';
  23. //insert form data in the database
  24. $insert = $db->query("INSERT uploading (name,email,file_name) VALUES ('".$name."','".$email."','".$path."')");
  25. //echo $insert?'ok':'err';
  26. }
  27. }
  28. else
  29. {
  30. echo 'invalid';
  31. }
  32. }
  33. ?>

Now that all the checks have been coded in, I will move the uploaded file from the tmp folder to the upload folder. For this, first, create an upload folder in the project directory. This is where the uploaded pictures will be saved. Where pathinfo() is the built-in function which will return the filename and extension in separate indexes.

Check if there are any errors in the upload

To check the error in the uploaded file, type in the following code, If the error is greater than zero then there must be an error in the process.

  1. if($errorimg > 0){
  2. die('<div class="alert alert-danger" role="alert"> An error occurred while uploading the file </div>');
  3. }

Check that the file is under the set file size limit

The file size is measured in bytes. So, if the file size is set at 500kb, then the file size should be less than 500000.

  1. if($myFile['size'] > 500000){
  2. die('<div class="alert alert-danger" role="alert"> File is too big </div>');
  3. }

Where move_uploaded_file is the function which will move the file from $myFile[“tmp_name”] (temporary location) to “upload/” . $name (permanent location) also check the database table record will be inserted.

How to Use reCAPTCHA in PHP Contact Form?

Recaptcha is a free service that protects forms from spamming and abusive submission. It’s an additional layer that works behind-the-scenes to prevent any spamming by differentiating if the end-user is a human or a bot, and give them the challenge to solve.

To place a reCAPTCHA on your PHP website, you must use a simple library that wraps around a reCHAPTCHA API. You can download the “reCAPTCHA PHP Library” and then use the file ‘recaptchalib.php’.

Add the following code in the <form> tag where you want your reCAPTCHA to be placed:

  1. require_once('recaptchalib.php');
  2. $publickey = "your_public_key"; //you got this from the signup page
  3. echo recaptcha_get_html($publickey);

To check whether the users have submitted the right answers or not, a “verify.php” file needs to be created and should be set as an ‘action’ parameter in the <form> tag. Here is the code below:

  1. <?php
  2. require_once('recaptchalib.php');
  3. $privatekey = "your_private_key";
  4. $resp = recaptcha_check_answer ($privatekey, $_SERVER["REMOTE_ADDR"], $_POST["recaptcha_challenge_field"], $_POST["recaptcha_response_field"]);
  5. if (!$resp->is_valid) {
  6. die ("The reCAPTCHA wasn't entered correctly. Go back and try it again." .
  7. "(reCAPTCHA said: " . $resp->error . ")");
  8. }
  9. else {
  10. // Your code here to handle a successful verification
  11. }
  12. ?>

Friday, October 30, 2020

Create, Update & Delete record with AJAX in DatTables using PHP

With the use of the DataTables jQuery plugin, you can list your records in pagination format.

You can add HTML elements like – buttons, link, image, etc with a record.

For this need to pass element in HTML string format from the PHP script.


NOTE – I am using the Bootstrap modal to update a record.


Contents

  1. Table structure
  2. Configuration
  3. Download & Include
  4. HTML
  5. PHP
  6. jQuery
  7. Output
  8. Conclusion

1. Table structure

Create users table and I added some records.

CREATE TABLE `users` (
  `id` int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
  `name` varchar(80) NOT NULL, 
  `gender` varchar(10) NOT NULL,
  `city` varchar(80) NOT NULL,
  `email` varchar(80) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

2. Configuration

Create a config.php for the database connection.

Completed Code

<?php

$host = "localhost"; /* Host name */
$user = "root"; /* User */
$password = ""; /* Password */
$dbname = "tutorial"; /* Database name */

$con = mysqli_connect($host, $user, $password,$dbname);
// Check connection
if (!$con) {
  die("Connection failed: " . mysqli_connect_error());
}

3. Download & Include

  • Download Datatables from here and Bootstrap from here.
  • Include datatables.min.cssbootstrap.min.css, jQuery library, bootstrap.min.js, and datatables.min.js in <head> section.
  • You can also use CDN.
<!-- Datatable CSS -->
<link href='//cdn.datatables.net/1.10.19/css/jquery.dataTables.min.css' rel='stylesheet' type='text/css'>

<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" >

<!-- jQuery Library -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>

<!-- Bootstrap CSS -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" ></script>

<!-- Datatable JS -->
<script src="//cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js"></script>

4. HTML

Create <div id="updateModal" > modal for update user details. Created a hidden field to store edit user id and <button id="btn_save"> to update user on click.

Display users list in <table id='userTable' >. On the last column, display the edit and delete button.

Completed Code

<!doctype html>
<html>
<head>
   <title>Edit delete DataTables record with AJAX and PHP</title>

   <meta name="viewport" content="width=device-width, initial-scale=1.0">

   <!-- Datatable CSS -->
   <link href='DataTables/datatables.min.css' rel='stylesheet' type='text/css'>

   <!-- Bootstrap CSS -->
   <link rel="stylesheet" type="text/css" href="bootstrap/css/bootstrap.min.css">

   <!-- jQuery Library -->
   <script src="jquery-3.5.1.min.js"></script>

   <!-- Bootstrap JS -->
   <script type="text/javascript" src="bootstrap/js/bootstrap.min.js"></script>

   <!-- Datatable JS -->
   <script src="DataTables/datatables.min.js"></script>

</head>
<body >

   <div class='container'>

     <!-- Modal -->
     <div id="updateModal" class="modal fade" role="dialog">
       <div class="modal-dialog">

         <!-- Modal content-->
         <div class="modal-content">
           <div class="modal-header">
             <h4 class="modal-title">Update</h4>
             <button type="button" class="close" data-dismiss="modal">&times;</button> 
           </div>
           <div class="modal-body">
             <div class="form-group">
               <label for="name" >Name</label>
               <input type="text" class="form-control" id="name" placeholder="Enter name" required> 
             </div>
             <div class="form-group">
               <label for="email" >Email</label> 
               <input type="email" class="form-control" id="email" placeholder="Enter email"> 
             </div> 
             <div class="form-group">
               <label for="gender" >Gender</label>
               <select id='gender' class="form-control">
                 <option value='male'>Male</option>
                 <option value='female'>Female</option>
               </select> 
             </div> 
             <div class="form-group">
               <label for="city" >City</label> 
               <input type="text" class="form-control" id="city" placeholder="Enter city"> 
             </div>

           </div>
           <div class="modal-footer">
             <input type="hidden" id="txt_userid" value="0">
             <button type="button" class="btn btn-success btn-sm" id="btn_save">Save</button>
             <button type="button" class="btn btn-default btn-sm" data-dismiss="modal">Close</button>
           </div>
         </div>

       </div>
     </div>

     <!-- Table -->
     <table id='userTable' class='display dataTable' width='100%'>
       <thead>
         <tr>
           <th>Name</th>
           <th>Email</th>
           <th>Gender</th>
           <th>City</th>
           <th>Action</th>
         </tr>
       </thead>
     </table>

   </div>

</body>
</html>

5. PHP

Create an ajaxfile.php file for handling AJAX requests.

Handle 4 requests –

If $request == 1 – Return DataTable response.

Read DataTable POST values and assign them in variables.

If $search is not empty then prepare search query and assign in $searchQuery variable.

Count total records with and without search filter and assign in variables. Fetch records from users table where pass $searchQuery in WHERE clause and specify ORDER BY and LIMIT.

Loop on the fetched records. Display update and delete buttons in DataTable using HTML string.

    • Create an update button and assign in $updateButton. In the button add 'updateUser' class and use data-id attribute to store user id. Add data-toggle and data-target attribute to open #updateModal modal.
    • Similarly, create delete button and assign in $deleteButton. In the button add 'deleteUser' class and use data-id attribute to store user id.

Concat $updateButton and $deleteButton and assign in $action variable.

Initialize $response Array with required values. Here, pass the $action in 'action' key.

Return $response Array in JSON format.

If $request == 2 – Return user details by id.

Assign $_POST['id'] to $id variable. Fetch a record from users table by id. If the number of fetched record is greater than 0 then read field values and initialize $response Array. Return an Array in JSON format that contains array("status" => 1,"data" => $response).

If the number of fetched record is 0 then Return an Array in JSON format that contains array("status" => 1).

If $request == 3 – Update field values by id.

Assign $_POST['id'] to $id variable. If $id is greater than 0 then read POST value and assign in a variable.

Check if $id is exists in the users table. If exists then check if variables are not empty then update a record by id and return Array in JSON format. Array contains array("status" => 1,"message" => "Record updated."). If variables are empty then return array("status" => 0,"message" => "Please fill all fields.") in JSON format.

If $id is not exists then return array("status" => 0,"message" => "Invalid ID.") in JSON format.

If $request == 4 – Delete a record by id.

Assign $_POST['id'] to $id variable. If $id is greater than 0 then read POST value and assign in a variable.

Check if $id is exists in the users table. If exist then delete a record from users table by id and return 1 otherwise return 0.

Completed Code

<?php
include 'config.php';

$request = 1;
if(isset($_POST['request'])){
   $request = $_POST['request'];
}

// DataTable data
if($request == 1){
   ## Read value
   $draw = $_POST['draw'];
   $row = $_POST['start'];
   $rowperpage = $_POST['length']; // Rows display per page
   $columnIndex = $_POST['order'][0]['column']; // Column index
   $columnName = $_POST['columns'][$columnIndex]['data']; // Column name
   $columnSortOrder = $_POST['order'][0]['dir']; // asc or desc

   $searchValue = mysqli_escape_string($con,$_POST['search']['value']); // Search value

   ## Search 
   $searchQuery = " ";
   if($searchValue != ''){
      $searchQuery = " and (name like '%".$searchValue."%' or 
         email like '%".$searchValue."%' or 
         city like'%".$searchValue."%' ) ";
   }

   ## Total number of records without filtering
   $sel = mysqli_query($con,"select count(*) as allcount from users");
   $records = mysqli_fetch_assoc($sel);
   $totalRecords = $records['allcount'];

   ## Total number of records with filtering
   $sel = mysqli_query($con,"select count(*) as allcount from users WHERE 1 ".$searchQuery);
   $records = mysqli_fetch_assoc($sel);
   $totalRecordwithFilter = $records['allcount'];

   ## Fetch records
   $empQuery = "select * from users WHERE 1 ".$searchQuery." order by ".$columnName." ".$columnSortOrder." limit ".$row.",".$rowperpage;
   $empRecords = mysqli_query($con, $empQuery);
   $data = array();

   while ($row = mysqli_fetch_assoc($empRecords)) {

     // Update Button
     $updateButton = "<button class='btn btn-sm btn-info updateUser' data-id='".$row['id']."' data-toggle='modal' data-target='#updateModal' >Update</button>";

     // Delete Button
     $deleteButton = "<button class='btn btn-sm btn-danger deleteUser' data-id='".$row['id']."'>Delete</button>";

     $action = $updateButton." ".$deleteButton;

     $data[] = array(
       "name" => $row['name'],
       "email" => $row['email'],
       "gender" => $row['gender'],
       "city" => $row['city'],
       "action" => $action
     );
   }

   ## Response
   $response = array(
     "draw" => intval($draw),
     "iTotalRecords" => $totalRecords,
     "iTotalDisplayRecords" => $totalRecordwithFilter,
     "aaData" => $data
   );

   echo json_encode($response);
   exit;
}

// Fetch user details
if($request == 2){
   $id = 0;

   if(isset($_POST['id'])){
      $id = mysqli_escape_string($con,$_POST['id']);
   }

   $record = mysqli_query($con,"SELECT * FROM users WHERE id=".$id);

   $response = array();

   if(mysqli_num_rows($record) > 0){
      $row = mysqli_fetch_assoc($record);
      $response = array(
         "name" => $row['name'],
         "email" => $row['email'],
         "gender" => $row['gender'],
         "city" => $row['city'],
      );

      echo json_encode( array("status" => 1,"data" => $response) );
      exit;
   }else{
      echo json_encode( array("status" => 0) );
      exit;
   }
}

// Update user
if($request == 3){
   $id = 0;

   if(isset($_POST['id'])){
      $id = mysqli_escape_string($con,$_POST['id']);
   }

   // Check id
   $record = mysqli_query($con,"SELECT id FROM users WHERE id=".$id);
   if(mysqli_num_rows($record) > 0){
 
      $name = mysqli_escape_string($con,trim($_POST['name']));
      $email = mysqli_escape_string($con,trim($_POST['email']));
      $gender = mysqli_escape_string($con,trim($_POST['gender']));
      $city = mysqli_escape_string($con,trim($_POST['city']));

      if( $name != '' && $email != '' && $gender != '' && $city != '' ){

         mysqli_query($con,"UPDATE users SET name='".$name."',email='".$email."',gender='".$gender."',city='".$city."' WHERE id=".$id);

         echo json_encode( array("status" => 1,"message" => "Record updated.") );
         exit;
      }else{
         echo json_encode( array("status" => 0,"message" => "Please fill all fields.") );
         exit;
      }

   }else{
      echo json_encode( array("status" => 0,"message" => "Invalid ID.") );
      exit;
   }
}

// Delete User
if($request == 4){
   $id = 0;

   if(isset($_POST['id'])){
      $id = mysqli_escape_string($con,$_POST['id']);
   }

   // Check id
   $record = mysqli_query($con,"SELECT id FROM users WHERE id=".$id);
   if(mysqli_num_rows($record) > 0){

      mysqli_query($con,"DELETE FROM users WHERE id=".$id);

      echo 1;
      exit;
   }else{
      echo 0;
      exit;
   }
}

6. jQuery

Initialize DataTables

Initialize DataTables on #userTable and assign in userDataTable. Set processing: true, serverSide: true, serverMethod: 'post'. Specify AJAX url with 'ajax' option.

With 'columns' option specifies key names that need to read from AJAX response.

Update User

Define click event on .updateUser class. Read user id from data-id attribute and assign in id variable. Update value of #txt_userid.

Send AJAX POST request to 'ajaxfile.php' file. Pass {request: 2, id: id}, set dataType: 'json'.
On successful callback check if response.status == 1 or not. If equals then read values from response.data and update the value of Bootstrap modal input elements.

Define click event on #btn_save. Read edit id from #txt_userid and assign in id variable. Similarly, read name, email, gender, and city from input elements and assign in variables.

If values are not empty then send AJAX POST request to 'ajaxfile.php' file. Pass {request: 3, id: id,name: name, email: email, gender: gender, city: city} as data. Set dataType: 'json'.

On successful callback check if response.status == 1 or not. If equals then alert(response.message) and reset input elements value.

Reload Datatable by calling userDataTable.ajax.reload() and toggle the #updateModal modal.

Delete User

Define click event on .deleteUser class. Read delete user id from data-id attribute. Display confirm alert message. If deleteConfirm == true then send AJAX POST request to 'ajaxfile.php' file. Pass {request: 4, id: id} as data.

On successful callback alert("Record deleted.") if response == 1 and reload Datatable by calling userDataTable.ajax.reload().

Completed Code

$(document).ready(function(){

  // DataTable
  var userDataTable = $('#userTable').DataTable({
     'processing': true,
     'serverSide': true,
     'serverMethod': 'post',
     'ajax': {
        'url':'ajaxfile.php'
     },
     'columns': [
        { data: 'name' },
        { data: 'email' },
        { data: 'gender' },
        { data: 'city' },
        { data: 'action' },
     ]
  });

  // Update record
  $('#userTable').on('click','.updateUser',function(){
     var id = $(this).data('id');

     $('#txt_userid').val(id);

     // AJAX request
     $.ajax({
        url: 'ajaxfile.php',
        type: 'post',
        data: {request: 2, id: id},
        dataType: 'json',
        success: function(response){
           if(response.status == 1){

             $('#name').val(response.data.name);
             $('#email').val(response.data.email);
             $('#gender').val(response.data.gender);
             $('#city').val(response.data.city);

             userDataTable.ajax.reload();
           }else{
             alert("Invalid ID.");
           }
        }
     });

  });

  // Save user 
  $('#btn_save').click(function(){
     var id = $('#txt_userid').val();

     var name = $('#name').val().trim();
     var email = $('#email').val().trim();
     var gender = $('#gender').val().trim();
     var city = $('#city').val().trim();

     if(name !='' && email != '' && city != ''){

       // AJAX request
       $.ajax({
         url: 'ajaxfile.php',
         type: 'post',
         data: {request: 3, id: id,name: name, email: email, gender: gender, city: city},
         dataType: 'json',
         success: function(response){
            if(response.status == 1){
               alert(response.message);

               // Empty and reset the values
               $('#name','#email','#city').val('');
               $('#gender').val('male');
               $('#txt_userid').val(0);

               // Reload DataTable
               userDataTable.ajax.reload();

               // Close modal
               $('#updateModal').modal('toggle');
            }else{
               alert(response.message);
            }
         }
      });

    }else{
       alert('Please fill all fields.');
    }
  });

  // Delete record
  $('#userTable').on('click','.deleteUser',function(){
     var id = $(this).data('id');

     var deleteConfirm = confirm("Are you sure?");
     if (deleteConfirm == true) {
        // AJAX request
        $.ajax({
          url: 'ajaxfile.php',
          type: 'post',
          data: {request: 4, id: id},
          success: function(response){
             if(response == 1){
                alert("Record deleted.");

                // Reload DataTable
                userDataTable.ajax.reload();
             }else{
                alert("Invalid ID.");
             }
          }
        });
     } 

  });
});




Wednesday, October 21, 2020

jQuery plugin: gentleSelect (Dropdown with multiple columns)

Intro

gentleSelect is a jQuery plugin for transforming select boxes into a skinnable alternative. The selection list can be rendered with multiple columns/rows to present larger datasets in a more manageable format. It recognizes the multiple attribute on select boxes and does the right thing automatically.

Source: http://shawnchin.github.io/jquery-gentleSelect/

Sunday, October 11, 2020

PHP JWT & REST API Authentication Tutorial: Login and Signup

 In this tutorial, we'll learn how to add JWT authentication to our REST API PHP application.

We'll see what JWT is and how it works. We'll also see how to get the authorization header in PHP.

We'll create REST API endpoints for allowing users to login and signup to access protected resources.

What is JWT

JWT stands for JSON Web Token and comprised of user encrypted information that can be used to authenticate users and exchange information between clients and servers.

When building REST API, instead of server sessions commonly used in PHP apps we tokens which are sent with HTTP headers from the server to clients where they are persisted (usually using local storage) then attached to every outgoing request originating from the client to the server. The server checks the token and allow or deny access to the request resource.

RESTful APIs are stateless. This means that requests from clients should contain all the necessary information required to process the request.

If you are building a REST API application using PHP, you are not going to use the $_SESSION variable to save data about the client's session.

This means, we can not access the state of a client (such as login state). In order to solve the issue, the client is responsible for perisiting the state locally and send it to the sever with each request.

Since these important information are now persisted in the client local storage we need to protect it from eyes dropping.

Enter JWTs. A JWT token is simply a JSON object that has information about the user. For example:

{
    "user": "bob",
    "email": "bob@email.com",
    "access_token": "at145451sd451sd4e5r4",
    "expire_at"; "11245454"
}

Since thos token can be tampered with to get access to protected resources. For example, a malicious user can change the previous token as follows to access admin only resources on the server:

{
    "user": "administrator",
    "email": "admin@email.com"
}

To prevent this situation, we JWTs need to be signed by the server. If the token is changed on the client side, the token's signature will no longer be valid and the server will deny access to the requested resource.

How JWT Works

JWT tokens are simply encrypted user's information like identifier, username, email and password.

When users are successfully logged in the server, the latter will produce and send a JWT token back to the client.

This JWT token will be persisted by the client using the browser's local storage or cookies and attached with every outgoing request so if the user requests access to certain protected resources, the token needs to be checked first by the server to allow or deny access.

What is PHP-JWT

php-jwt is a PHP library that allows you to encode and decode JSON Web Tokens (JWT) in PHP, conforming to RFC 7519.

Prerequisites

You must have the following prerequsites to be able to follow this tutorial from scratch:

  • You need PHP 7, Composer and MySQL database system installed on your development environment,
  • You need to have basic knowledge of PHP and SQL.

Creating the MySQL Database and Table(s)

If you have the prerequisites, let's get started by creating the MySQL database. We'll be using the MySQL client installed with the server. Open a terminal and run the following command to invoke the client:

$ mysql -u root -p

You need to enter your MySQL password when prompted.

Next, let's create a database using the following SQL instruction:

mysql> create database db;

Note: Here we assume you have a MySQL user called root. You need to change that to the name of an existing MySQL user.

You can also use phpMyAdmin or any MySQL client you are comfortable with to create the database and SQL tables.

Let's now select the db database and create a users table that will hold the users of our application:

mysql> use db;
mysql> CREATE  TABLE IF NOT EXISTS `Users` (
  `id` INT  AUTO_INCREMENT ,
  `first_name` VARCHAR(150) NOT NULL ,
  `last_name` VARCHAR(150) NOT NULL ,
  `email` VARCHAR(255),
  `password` VARCHAR(255),
  PRIMARY KEY (`id`) );

Creating the Project Directory Structure

Let's create a simple directory strucutre for our project. In your terminal, navigate to your working directory and create a folder for our project:

$ mkdir php-jwt-example
$ cd php-jwt-example
$ mkdir api && cd api
$ mkdir config

We first created the project's directory.

Next, we created an api folder. Inside it, we created a config folder.

Connecting to your MySQL Database in PHP

Navigate to the config folder and create a database.php file with the following code:

<?php
// used to get mysql database connection
class DatabaseService{

    private $db_host = "localhost";
    private $db_name = "mydb";
    private $db_user = "root";
    private $db_password = "";
    private $connection;

    public function getConnection(){

        $this->connection = null;

        try{
            $this->connection = new PDO("mysql:host=" . $this->db_host . ";dbname=" . $this->db_name, $this->db_user, $this->db_password);
        }catch(PDOException $exception){
            echo "Connection failed: " . $exception->getMessage();
        }

        return $this->connection;
    }
}
?>

Installing php-jwt

Let's now proceed to install the php-jwt library using Composer. In your terminal, run the following command from the root of your project's directory:

$ composer require firebase/php-jwt

This will donwload the php-jwt library into a vendor folder.

You can require the php-jwt library to encode and decode JWT tokens using the following code:

<?php 
require "vendor/autoload.php";
use \Firebase\JWT\JWT;

Adding the User Registration API Endpoint

Inside the api folder, create a register.php file and add the following code to create a new user in the MySQL database:

<?php
include_once './config/database.php';

header("Access-Control-Allow-Origin: * ");
header("Content-Type: application/json; charset=UTF-8");
header("Access-Control-Allow-Methods: POST");
header("Access-Control-Max-Age: 3600");
header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");

$firstName = '';
$lastName = '';
$email = '';
$password = '';
$conn = null;

$databaseService = new DatabaseService();
$conn = $databaseService->getConnection();

$data = json_decode(file_get_contents("php://input"));

$firstName = $data->first_name;
$lastName = $data->last_name;
$email = $data->email;
$password = $data->password;

$table_name = 'Users';

$query = "INSERT INTO " . $table_name . "
                SET first_name = :firstname,
                    last_name = :lastname,
                    email = :email,
                    password = :password";

$stmt = $conn->prepare($query);

$stmt->bindParam(':firstname', $firstName);
$stmt->bindParam(':lastname', $lastName);
$stmt->bindParam(':email', $email);

$password_hash = password_hash($password, PASSWORD_BCRYPT);

$stmt->bindParam(':password', $password_hash);


if($stmt->execute()){

    http_response_code(200);
    echo json_encode(array("message" => "User was successfully registered."));
}
else{
    http_response_code(400);

    echo json_encode(array("message" => "Unable to register the user."));
}
?>

Adding the User Login API Endpoint

Inside the api folder, create a login.php file and add the following code to check the user credentials and return a JWT token to the client:

<?php
include_once './config/database.php';
require "../vendor/autoload.php";
use \Firebase\JWT\JWT;

header("Access-Control-Allow-Origin: *");
header("Content-Type: application/json; charset=UTF-8");
header("Access-Control-Allow-Methods: POST");
header("Access-Control-Max-Age: 3600");
header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");


$email = '';
$password = '';

$databaseService = new DatabaseService();
$conn = $databaseService->getConnection();



$data = json_decode(file_get_contents("php://input"));

$email = $data->email;
$password = $data->password;

$table_name = 'Users';

$query = "SELECT id, first_name, last_name, password FROM " . $table_name . " WHERE email = ? LIMIT 0,1";

$stmt = $conn->prepare( $query );
$stmt->bindParam(1, $email);
$stmt->execute();
$num = $stmt->rowCount();

if($num > 0){
    $row = $stmt->fetch(PDO::FETCH_ASSOC);
    $id = $row['id'];
    $firstname = $row['first_name'];
    $lastname = $row['last_name'];
    $password2 = $row['password'];

    if(password_verify($password, $password2))
    {
        $secret_key = "owt56789"; //add here your secret key
        $issuer_claim = "localhost"; // this can be the servername
        $audience_claim = "myusers"; //your audience
        $issuedat_claim = time(); // issued at
        $notbefore_claim = $issuedat_claim + 10; //not before in seconds
        $expire_claim = $issuedat_claim + 60; // expire time in seconds
        $token = array(
            "iss" => $issuer_claim,
            "aud" => $audience_claim,
            "iat" => $issuedat_claim,
            "nbf" => $notbefore_claim,
            "exp" => $expire_claim,
            "data" => array(
                "id" => $id,
                "firstname" => $firstname,
                "lastname" => $lastname,
                "email" => $email
        ));

        http_response_code(200);

        $jwt = JWT::encode($token, $secret_key);
        echo json_encode(
            array(
                "message" => "Successful login.",
                "jwt" => $jwt,
                "email" => $email,
                "expireAt" => $expire_claim
            ));
    }
    else{

        http_response_code(401);
        echo json_encode(array("message" => "Login failed.", "password" => $password));
    }
}
?>

You can define the data structure of the token as you want i.e (You can add only the user's email or ID or both with any extra information like the user's name) but there are some reserved JWT claims that should be defined properly because they affect the validity of the JWT token, such as:

  • iat – timestamp of token issuing.

  • iss – A string containing the name or identifier of the issuer application. Can be a domain name and can be used to discard tokens from other applications.

  • nbf – Timestamp of when the token should start being considered valid. Should be equal to or greater than iat. In this case, the token will begin to be valid after 10 seconds after being issued

  • exp – Timestamp of when the token should stop to be valid. Needs to be greater than iat and nbf. In our example, the token will expire after 60 seconds of being issued.

These claims are not required, but are useful for determining the validity of a token.

Our JWT payload is inside the data claim, we added the first name, last name, email and user ID from the database. You shouldn't add any sensitive information in the JWT payload.

The JWT::encode() method will transform the PHP array into JSON format and sign the payload then encode the final JWT token that will be sent to the client. In our example, we simply hradcoded the secret key that will be used for signing the JWT payload but in production, you need to make sure you use a secret key with a long, binary string, store it in a configuration file.

We now have two RESTful endpoints for registering and log users in. At this point, you can use a REST client like Postman to intercat with the API.

First, start your PHP server using the following command:

$ php -S 127.0.0.1:8080

A development server will be running from the 127.0.0.1:8080 address.

Let's now, create a user in the database by sending a POST request to the api/register.php endpoint with a JSON body that contains the first_namelast_nameemail and password:

PHP JWT Authentication Example

You should get an 200 HTTP response with a User was successfully registered. message.

Next, you need to send a POST request to the /api/login.php endpoint with a JSON body that contains the email and password used for registering the user:

PHP JWT Authentication Example

You should get a Successful login message with a JWT token.

The JWT token needs to be persisted in your browser's local storage or cookies using JavaScript then attached to each send HTTP request to access a protected resource on your PHP server.

Protecting an API Endpoint Using JWT

Let's now see how we can protected our server endpoints using JWT tokens.

Before accessing an endpoint a JWT token is sent with every request from the client. The server needs to decode the JWT and check if it's valid before allowing access to the endpoint.

Inside the api folder, create a protected.php file and add the following code:

<?php
include_once './config/database.php';
require "../vendor/autoload.php";
use \Firebase\JWT\JWT;

header("Access-Control-Allow-Origin: *");
header("Content-Type: application/json; charset=UTF-8");
header("Access-Control-Allow-Methods: POST");
header("Access-Control-Max-Age: 3600");
header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");


$secret_key = "YOUR_SECRET_KEY";
$jwt = null;
$databaseService = new DatabaseService();
$conn = $databaseService->getConnection();

$data = json_decode(file_get_contents("php://input"));


$authHeader = $_SERVER['HTTP_AUTHORIZATION'];

$arr = explode(" ", $authHeader);


/*echo json_encode(array(
    "message" => "sd" .$arr[1]
));*/

$jwt = $arr[1];

if($jwt){

    try {

        $decoded = JWT::decode($jwt, $secret_key, array('HS256'));

        // Access is granted. Add code of the operation here 

        echo json_encode(array(
            "message" => "Access granted:",
            "error" => $e->getMessage()
        ));

    }catch (Exception $e){

    http_response_code(401);

    echo json_encode(array(
        "message" => "Access denied.",
        "error" => $e->getMessage()
    ));
}

}
?>

Note: We assume that the client sends the JWT token inside an HTTP Authorization header in the JWT <token> or Bearer <token> formats. You can also choose to include the token as a parameter in the request URL or as part of data payload sent from the client if you don't want to deal with HTTP headers.

You can now send a POST request with an Authorization header in the following formats:

JWT <YOUR_JWT_TOKEN_HERE> 

Or also using the bearer format:

Bearer <YOUR_JWT_TOKEN_HERE>

PHP JWT

Conclusion

In this tutorial, we've seen how to implement REST API JWT authentication in PHP and MySQL.

Credit & Source: https://www.techiediaries.com/php-jwt-authentication-tutorial/?fbclid=IwAR27DtqFhlZxec5lJV4Y0WOwUlFdFU9pinfQ7LZ8PjotI6zSXgyGp1ZlWcs


Friday, October 2, 2020

How to forbidden Right Click, ctrl+c, ctrl+u, and F12 with javascript

 // To disable right click

document.addEventListener('contextmenu', event => event.preventDefault());

// To disable F12 options

document.onkeypress = function (event) {

event = (event || window.event);

if (event.keyCode == 123) {

return false;

}

}

document.onmousedown = function (event) {

event = (event || window.event);

if (event.keyCode == 123) {

return false;

}

}

document.onkeydown = function (event) {

event = (event || window.event);

if (event.keyCode == 123) {

return false;

}

}

// To To Disable ctrl+c, ctrl+u

jQuery(document).ready(function($){

$(document).keydown(function(event) {

var pressedKey = String.fromCharCode(event.keyCode).toLowerCase();

if (event.ctrlKey && (pressedKey == "c" || pressedKey == "u")) {

alert('Sorry, This Functionality Has Been Disabled!');

//disable key press porcessing

return false;

}

});

});

How to change the PHP version for subfolders or subdomains

  How to change the PHP version for subfolders or subdomains Setting a specific PHP version for a specific websites, subfolders or subdomain...