background image
HomeRecent PostsDrupalSearchTagsRSSContactAboutAccount
Eric.London's picture

In this code snippet tutorial, I'll show how you can use the PEAR library HTML_QuickForm2 to create a simple authentication form with a custom validation callback.

<?php
// start session
session_start();

// check if user needs to authenticate
if (empty($_SESSION['accountID'])) {
 
 
// show form
 
require_once('HTML/QuickForm2.php');
 
// NOTE: have the form submit to itself
 
$form = new HTML_QuickForm2('login', 'post', array('action' => $_SERVER['REQUEST_URI']));

 
// add username field
 
$username = $form->addElement('text', 'username')->setLabel('username:');
 
$username->addRule('required', 'username is required.');

 
// add password field
 
$password = $form->addElement('password', 'password')->setLabel('password:');
 
$password->addRule('required', 'password is required.');

 
// add submit button
 
$form->addElement('submit', null, array('value' => 'submit'));

 
// add filter to trim all elements
 
$form->addRecursiveFilter('trim');

 
// add custom validation rule
 
$form->addRule(
   
'callback',
   
'authentication failed.',
    array(
     
'callback' => 'portal_authentication_validation',
    )
  );

 
// check if form validates
 
if ($form->validate()) {
   
   
// at this point, the form has validated, set session data as authentication
    // NOTE: at this point, the account ID should be fetched from the database, etc
   
$_SESSION['accountID'] = 'some_val';
   
   
// redirect user (reload url)
   
header("Location: " . $_SERVER['REQUEST_URI']);
    die;
   
  }
 
// form did not pass validation, display form
 
else {

   
// display form
   
echo $form;
 
  }
  
}
// user is already authenticated..
else {

 
// do something here!
 
echo "Hello Auth User!";

}

// defines custom validation callback function
function portal_authentication_validation($form_args) {

 
/*
  Args..
  $form_args['username']
  $form_args['password']
  */

  // At this point, query the database to validate username/password, etc
 
if ($user_and_password_validates) {
    return
TRUE:
  }
 
  return
FALSE;

}
?>

The above code will result in the following form:
Authentication form

Eric.London's picture

I felt it would be more secure for a user to be logged out when they close their browser. This can be done by editing your settings.php file. The default location for this is /sites/default/settings.php. Located this line of code:

<?php
ini_set
('session.cookie_lifetime'2000000);
?>

And change it to:
<?php
ini_set
('session.cookie_lifetime'0);
?>

This is the default PHP setting.

Here is the code I used in a module and theme to logout a user after 15 minutes of activity. The code uses jQuery, AJAX, sessions, and a menu callback function to keep track how it's been since the user loaded a page.

The first piece of code I added was a menu callback to simply output the number of minutes of inactivity, which will be used by AJAX.

<?php
MYMODULE_menu
() {
 
// ...code...
 
$items[] = array(
   
'path' => 'sessionTimeout',
   
'callback' => 'MYMODULE_sessionTimeout',
   
'type' => MENU_CALLBACK,
   
'access' => TRUE,
  ); 
 
// ...code...
}
?>

Here's the callback function used...

<?php
MYMODULE_sessionTimeout
() {
 
// ensure the user is logged in
 
if (!$GLOBALS['user']->uid) die;

 
// if session data does not exist, create it
 
if (!isset($_SESSION['sessionTimestamp']) || strlen($_SESSION['sessionTimestamp'])==0) $_SESSION['sessionTimestamp'] = strtotime("now");

 
// show how long it's been since a page loaded in in minutes
 
echo intval((strtotime("now") - $_SESSION['sessionTimestamp'])/60);
  
 
// this die is important, or your theme will be processed
 
die;
}
?>

Next, I created a function that will increment the session timestamp. As you can see, I used variable_get(). Whenever I feel like something should be configurable to the site administrator, I make sure to create an admin settings form (which I'm not showing in this example).

<?php
_MYMODULE_update_session_timeout
() {
 
// ensure the user is logged in
 
if (!$GLOBALS['user']->uid) return;
   
 
// define session timeout in minutes
 
$sessionTimeout = variable_get('session_timeout', 15);
   
 
// if session data does not exist, create it
 
if (!isset($_SESSION['sessionTimestamp']) || strlen($_SESSION['sessionTimestamp'])==0) $_SESSION['sessionTimestamp'] = strtotime("now");

 
$timeInactive = intval((strtotime("now") - $_SESSION['sessionTimestamp'])/60);

  if (
$timeInactive > $sessionTimeout) {
    unset(
$_SESSION['sessionTimestamp']);
   
drupal_goto('logout');
  }
   
 
// update last page load
 
$_SESSION['sessionTimestamp'] = strtotime("now");
}
?>

I wanted this piece of code to be executed on every page load, so I put it right at the top of my menu hook...

<?php
MYMODULE_menu
() {
 
// check session timeout
 
if (arg(0)!='sessionTimeout') _MYMODULE_update_session_timeout();
 
// ...code....
}
?>

In the head of my theme, I added a line of code to set the session timeout so it will be available to jQuery. NOTE: I should have used drupal_add_js(), I'll have to change my code.

<?php
<script type="text/javascript">
  var
sessionTimeout = < ? php print variable_get('session_timeout', 15); ? >;
</script>
?>

Lastly, I added some jQuery to a javascript include file...

<?php
$(document).ready(function(){
 
checkSession();
});

function
checkSession() {
 
result = $.ajax({
   
type: "GET",
   
url: "/sessionTimeout",
   
success: function(html){
      if (
parseInt(html)==html && html>sessionTimeout) {
        $.
ajax({
         
type: "GET",
         
url: "/logout",
         
success: function(html){
           
alert("Sorry, you have been inactive for over " + sessionTimeout + " minutes. As a safety precaution, we have logged you out of the system. Sorry for the inconvenience.");
           
window.location = "/";
          }
        });
      }
    }
  });
 
setTimeout("checkSession()", 60000);
}
?>

Now, if the user leaves their browser open for 15 minutes without clicking on anything, they'll get a popup window telling them their session expired, they'll be logged out, and redirected to the homepage. If the user closes their browser and returns to the site a while later, they will also be logged out.

Syndicate content