Ajax login only working half the time?

http://www.codefundamentals.com/cadeui/login.php

<?php
require_once($_SERVER['DOCUMENT_ROOT']."/cadeui/system/includes/db-config.php");
$page="Login";
require_once($_SERVER['DOCUMENT_ROOT']."/cadeui/system/includes/header.php");
?>
<body id="login-page">
<div class="login-wrapper">
  <div class="logo">
    <img src="http://guelphtoyota.com/wordpress/wp-content/uploads/2012/09/blank-profile.png" alt="CadeUI Logo">
    <h1>CadeUI</h1>
  </div>
  <form method="post" action="<?php echo $_SERVER['PHP_SELF'];?>" id="login" name="login">
    <fieldset>
        <label for"email">Username</label>
      	<input type="text" class="envelope" placeholder="Username" id="email" name="email">
        <div class="password-holder">
          <label for="password">Password</label>
          <span class="showHide showPW remove">Show</span>
        </div>
        <input type="password" class="lock" placeholder="Password" id="password" name="password">
        <div class="submit-holder">
          <a href="#" class="forgotpw">I forgot my password...</a>
          <input type="submit" id="submit" value="Login">
        </div>
     </fieldset>
  </form>
</div>
<?php
if(isset($_POST['login']))
{
  $pdo=new PDO('mysql:dbname=codefund_user_login', 'codefund', 'pw!');
  $login = new LoginRepository($pdo);
  if($login->checkCredentials($_POST['email'],$_POST['password']))
    echo "login went good";
}
require_once($_SERVER['DOCUMENT_ROOT']."/cadeui/system/includes/js-files.php");
?>
</body>
</html>

I notice that when I login with
admin@codefundamentals.com
password

I try logging in again and it doesn’t give that alert letting me know it was successful. Playing with it it just doesn’t work 100% of the time. Can anyone identify why? Also, anything you’d change about the ajax login?

Edit-Not working at all now?

Added a hidden input and checked the isset($_POST) on that and it seems to fix everything.

Thanks.

1 Like

Hmm, wait. Blank form…click submit, and th e ajax alert on succcess still goes through.

How can I link up the jquery validation, and the ajax login (only do the ajax login if the validation goes through?)

Then what’s wrong with the ajax login?

PHP

<?php
if(isset($_POST['submitted']))
{
  $pdo=new PDO('mysql:dbname=codefund_user_login', 'codefund', 'pw');
  $login = new LoginRepository($pdo);
  if($login->checkCredentials($_POST['email'],$_POST['password']))
    echo "login went good";
}
require_once($_SERVER['DOCUMENT_ROOT']."/cadeui/system/includes/js-files.php");
?>

I need an answer as to why the ajax login isn’t actually properly working. It’s giving me feedback on success but I think that feedback is only if it connected to the page properly? Why is my data failing?

$("#login").submit(function(event) {
    var user=$("#email").val();
    var pass=$("#password").val();
    if($("#login").valid())
    {
      $.ajax({
        type: "POST",
        data: { email: user, password: pass },
        url: "login.php",
        success: function() {
          console.log('good ');
          $("#msg").css("color","red");//visual cue
        }
      });
      return true;
    }
    else
      return false;
  });

Are you sure that the form isn’t being submitted normally before the ajax submission has completed - resulting in the page being reloaded and therefore not giving that visual notification.

1 Like

The form does SERVER SELF and I just realized my Javascript doesn’t have preventDefault on submit. Added that in.
http://www.codefundamentals.com/cadeui/login.php

I notice that it only flashes red and then goes back to black. It still refreshes.

Also it still flashes red for invalid input.

Correct input is admin@codefundamentals.com//password

Alright I removed the return true and at the end forced a return false.

$("#login").submit(function(event) {
    event.preventDefault();
    var user=$("#email").val();
    var pass=$("#password").val();
    if($("#login").valid())
    {
      $("#submit").prop("disabled", true);
      $("#email").prop("disabled", true);
      $("#password").prop("disabled", true);
      $.ajax({
        type: "POST",
        data: { email: user, password: pass },
        url: "login.php",
        success: function() {
          console.log('good shit');
          $("#msg").css("color","red");
        }
      });
    }
    return false;
  });

This works MINUS the data validating. The success still only seems to be based off it correctly connecting to login.php. The data I enter is invalid yet it still finds the success function and highlights that msg element as red.

   $.post('login.php', loginData /*username and password object(s)*/, function (response) { // Check to see what the response is you get back:
      console.log('good shit');
      $("#msg").css("color","red");
    }).fail(function (xhr, textStatus, errorThrown) {
       // Errors use console.log() the see what xhr, textStatus, errorThrown do:
    }); // End of Login Ajax Post function(s):

Of course you will have to change your php file to reflect the changes on the php side:

Here's a few snippets from my login php utilizing Ajax


     /* Makes is so we don't have to decode the json coming from JQuery */
        header('Content-type: application/json');

$data['username'] = filter_input(INPUT_POST, 'username', FILTER_SANITIZE_SPECIAL_CHARS);
$data['password'] = filter_input(INPUT_POST, 'password', FILTER_SANITIZE_SPECIAL_CHARS);



if (isset($data['username'])) {

  $result = $login->read($data);

  if ($result) {
    $user = $_SESSION['user'];
    $output = json_encode(['type' => 'success', 'class' => 'displayOn', 'user' => $user->username]);
    output($output);
  }
  
}

/* If there is an error then change the error to the proper code and output the */
/* error message via Ajax /JQuery.                                              */
function error($output, $code = 500) {
  http_response_code($code);  
  echo $output;
}

/* If everything validates OK then send success message to Ajax/jQuery */
function output($output) {
  http_response_code(200);
  echo $output;
}

This might help you out and if you need help implementing it in your code I glady help in-between working on my own project(s). Sorry about that I used post instead of $.ajax → however you can do the same thing with ajax also.

Sorry, that post seems a bit confusing. Why do I need the .post() function? Does ajax() not do what I want?

I did try and the console outputtted my entire login.php file, along with saying Status: Success

$("#login").submit(function(event) {
    event.preventDefault();
    if($("#login").valid())
    {
      var user=$("#email").val();
      var pass=$("#password").val();
      $("#submit").prop("disabled", true);
      $("#email").prop("disabled", true);
      $("#password").prop("disabled", true);
      console.log(user);console.log(pass);
      /*$.ajax({
        type: "POST",
        dataType:"json",
        data: { email:user,password:pass },
        url: "login.php",
        success: function() {
          console.log('good shit');
          $("#msg").css("color","red");
        }
      });*/
$.post("login.php",
        {
          email : user,
          password: pass
        },
        function(data,status){
            console.log("Data: " + data + "\nStatus: " + status);
        });
    }
    return false;
  });

Still seems to be validating incorrect data.

Alright it’s working but I’d like help on this. I managed to get it properly validating the data.

$("#login").submit(function(event) {
    event.preventDefault();
    if($("#login").valid())
    {
      var user=$("#email").val();
      var pass=$("#password").val();
      $("#submit").prop("disabled", true);
      $("#email").prop("disabled", true);
      $("#password").prop("disabled", true);
      $.ajax({
        type: "POST",
        dataType: "text",
        data: {
          'email': user,
          'password':pass,
          'action':'login'
        },
        url: "system/includes/ajax.php",
        success: function(data) {
          data = JSON.parse(data);
          if(data.success)
             $("#msg").css("color","green");
          else
             $("#msg").css("color","red");
        }
      });
    }
    return false;
  });

I have the data sent to ajax.php

<?php
require_once($_SERVER['DOCUMENT_ROOT']."/cadeui/system/includes/db-config.php");
$data = $_POST;
if($data['action']==="login")
{
  $pdo=new PDO('mysql:dbname=codefund_user_login', 'codefund', 'pw!');
  $login = new LoginRepository($pdo);
  if($login->checkCredentials($data['email'],$data['password']))
    echo json_encode(array('success'=>true));
  else
    echo json_encode(array('success'=>false));
}
?>

login.php

<?php
require_once($_SERVER['DOCUMENT_ROOT']."/cadeui/system/includes/db-config.php");
$page="Login";
require_once($_SERVER['DOCUMENT_ROOT']."/cadeui/system/includes/header.php");
?>
<body id="login-page">
<div class="login-wrapper">
  <div class="logo">
    <img src="http://guelphtoyota.com/wordpress/wp-content/uploads/2012/09/blank-profile.png" alt="CadeUI Logo">
    <h1>CadeUI</h1>
  </div>
  <form method="post" action="<?php echo $_SERVER['PHP_SELF'];?>" id="login" name="login">
    <fieldset>
        <label for"email">Username</label>
      	<input type="text" class="envelope" placeholder="Username" id="email" name="email">
        <div class="password-holder">
          <label for="password">Password</label>
          <span class="showHide showPW remove">Show</span>
        </div>
        <input type="password" class="lock" placeholder="Password" id="password" name="password">
        <div class="submit-holder">
          <a href="#" class="forgotpw">I forgot my password...</a>
          <input type="submit" id="submit" value="Login">
          <input type="hidden" name="submitted">
        </div>
     </fieldset>
  </form>
<div id="msg">should be colored green on ajax success, red on fail</div>
</div>
<?php
if(isset($_POST['submitted']))
{
  $pdo=new PDO('mysql:dbname=codefund_user_login', 'codefund', 'pw!');
  $login = new LoginRepository($pdo);
  if($login->checkCredentials($_POST['email'],$_POST['password']))
    echo "login went good";
}
require_once($_SERVER['DOCUMENT_ROOT']."/cadeui/system/includes/js-files.php");
?>
</body>
</html>

Is there any way to just have that ajax url just be the same login page as my form? In PHP I have the form sent to SERVER SELF, but that will only be used if Javascript is off. If Javascript is on, then it gets sent to ajax.php. I don’t want to have to maintain two copies of my login script depending on that.

Can anyone combine this to where I only have one login form to maintain? Preferably just remove the ajax.php.

The LoginRepository checkCredentials() you see in my login.php file just returns true if the data is valid. False otherwise.

One option would be to remove the login code from the form page and have a separate script that processes the login independently of how the data was submitted. This also has the advantage of keeping the logic out of your view.

processLogin.php

<?php

if ($_SERVER['REQUEST_METHOD'] == 'POST') {

    require_once($_SERVER['DOCUMENT_ROOT']."/cadeui/system/includes/db-config.php");

    $pdo   = new PDO('mysql:dbname=codefund_user_login', 'codefund', 'pw!');
    $login = new LoginRepository($pdo);

    // Strictly speaking, you don't need filter_input here
    // but it handles unset $_POST variables (returning NULL).
    $email    = filter_input(INPUT_POST, 'email');
    $password = filter_input(INPUT_POST, 'password');

    $isValidLogin = $login->checkCredentials($email, $password);
    $isAjax = !empty($_SERVER['HTTP_X_REQUESTED_WITH']) 
            && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest';
    
    if ($isAjax) {
        $result = [ 'success' => $isValidLogin ];
        header('Content-Type: application/json');
        exit(json_encode($result));
    }

    if ($isValidLogin) {
        header('Location: http://www.example.com/admin.php');
    } else {
        // You could set session vars here if you wanted to return more info to the form 
        // page (e.g. validation errors).
        header('Location: http://www.example.com/login.php?status=failed');
    }
}
2 Likes

@fretburner beautiful; that looks like it’s what I want.

So on my login.php page, change the form action to processLogin.php, put that code in, and …I don’t see where the AJAX would work in with that though? Perhaps I’m missing a few dots in my head.

Just change the URL in your JS to processLogin.php. The PHP script looks for a header that jQuery sets on all of its http requests, and returns JSON instead of redirecting the page.

Alright I did that but it doesn’t work. I looked at the console and I’m getting a 500 error when I attempt to sign in.

<?php

if ($_SERVER['REQUEST_METHOD'] == 'POST')
{
  require_once($_SERVER['DOCUMENT_ROOT']."/cadeui/system/includes/db-config.php");

  $pdo   = new PDO('mysql:dbname=codefund_user_login', 'codefund', 'pw!');
  $login = new LoginRepository($pdo);

  // Strictly speaking, you don't need filter_input here
  // but it handles unset $_POST variables (returning NULL).
  $email    = filter_input(INPUT_POST, 'email');
  $password = filter_input(INPUT_POST, 'password');

  $isValidLogin = $login->checkCredentials($email, $password);
  $isAjax = !empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest';

  if($isAjax)
  {
    $result = [ 'success' => $isValidLogin ];
    header('Content-Type: application/json');
    exit(json_encode($result));
  }
  if ($isValidLogin)
  {
    header('Location: http://www.code.com/cadeui/login?login=success');
  }
  else
  {
    header('Location: http://www.code.com/cadeui/login?login=fail');
  }
}

Oops - I didn’t put my password back.

That works - thanks :slight_smile: . How can I get rid of the login though on my login.php? You say I only needed to update the ajax.php to processLogin?

Should I point the form action to processLogin?

<?php
require_once($_SERVER['DOCUMENT_ROOT']."/cadeui/system/includes/db-config.php");
$page="Login";
require_once($_SERVER['DOCUMENT_ROOT']."/cadeui/system/includes/header.php");
?>
<body id="login-page">
<div class="login-wrapper">
  <div class="logo">
    <img src="http://guelphtoyota.com/wordpress/wp-content/uploads/2012/09/blank-profile.png" alt="CadeUI Logo">
    <h1>CadeUI</h1>
  </div>
  <form method="post" action="<?php echo $_SERVER['PHP_SELF'];?>" id="login" name="login">
    <fieldset>
        <label for"email">Username</label>
      	<input type="text" class="envelope" placeholder="Username" id="email" name="email">
        <div class="password-holder">
          <label for="password">Password</label>
          <span class="showHide showPW remove">Show</span>
        </div>
        <input type="password" class="lock" placeholder="Password" id="password" name="password">
        <div class="submit-holder">
          <a href="#" class="forgotpw">I forgot my password...</a>
          <input type="submit" id="submit" value="Login">
          <input type="hidden" name="submitted">
        </div>
     </fieldset>
  </form>
<div id="msg">should be colored green on ajax success, red on fail</div>
</div>
<?php
if(isset($_POST['submitted']))
{
  $pdo=new PDO('mysql:dbname=codefund_user_login', 'codefund', 'pw!');
  $login = new LoginRepository($pdo);
  if($login->checkCredentials($_POST['email'],$_POST['password']))
    echo "login went good";
}
require_once($_SERVER['DOCUMENT_ROOT']."/cadeui/system/includes/js-files.php");
?>
</body>
</html>

Yes that’s right, and then you don’t need that section of PHP from beneath the form.

EDIT: Btw, if you hit the Reply button beneath the post that you’re replying to (rather than the one at the bottom of the page) the other user will get a notification - it makes it easier, as otherwise I don’t always notice that you’ve replied unless I check back on the thread. :slight_smile:

1 Like

Cool! It’s working now. All fixed; thanks!

I did switch up your filter_input for the filter sanitize functions in PHP (string) . I assume that will still return null if empty?

  $email=filter_var($_POST['email'], FILTER_SANITIZE_STRING);
  $password=filter_var($_POST['password'], FILTER_SANITIZE_STRING);

@fretburner

There’s no practical difference between using filter_var or filter_input here, but filter_var will return “” (an empty string) if the variable is not set, plus trigger a PHP notice.

Also, be aware that there’s a difference between using FILTER_SANITIZE_STRING and FILTER_SANITIZE_EMAIL - the first will allow characters that are invalid in an email address. It’s unlikely to be a problem in this situation as you already have the user’s email in the DB, but good to be aware of when filtering input for signup forms.

Oops - I actually forgot my username was going to be an e-mail. Great catch. I’m switching to EMAIL

Thanks @fretburner.

How do I go about setting PHP sessions? I tried this

  if($isAjax)
  {
    $result = [ 'success' => $isValidLogin ];
    header('Content-Type: application/json');
    exit(json_encode($result));
  }
  if($isValidLogin)
  {
    $_SESSION['test']="pleasework";
    header('Location: http://www.codefundamentals.com/cadeui/dashboard');
  }
  else
  {
    header('Location: http://www.codefundamentals.com/cadeui/login');
  }

Which I assume will only work on the non-javascript login, but I’m unsure how I can set them in jquery.

On the dashboard.php file I just echo $_SESSION[‘test’].

PS - at the top of that file processLogin I put a session_start().