0

I am attempting to create a login page, in which, every attempt at a login is done on the page, straight away; rather than refreshing the page. Something along the lines of how Google do their login page, and how Facebook submit messages without refresh.

I have programmed the backend functionality of the page in PHP and now I would like to give it that little more to make it look and function exceptionally.

This is the current Ajax script I am using which doesn't want to work the way I would like it to (I have tried multiple others with the same results):

<script>
    $(function () {
        $('#_js_pdTr1').on('submit', function (e) {

            e.preventDefault();

            $.ajax({
                type: 'post',
                url: 'login_push.php',
                data: $('#_js_pdTr1').serialize(),
            });
        });
    });
</script>

This is the form for the page:

<form id="_js_pdTr1" action="" method="post">
    <h3>LOGIN</h3>
    <div class="err-disp-out">
        <?php
            if(!empty($errors)){
                echo output_errors($errors);
            }
        ?>
    </div>
    <input type="text" name="username" placeholder="Username"><br><br>
    <input type="password" name="password" placeholder="Password"><br><br>
    <input id="remember" type="checkbox" name="remember_me"><label for="remember">Remember Me</label><br><br>
    <button id="_js_pdTr2" type="submit">Login</button>
</form>

and on my login_push.php page, this is the PHP:

include 'core/init.php';
logged_in_protect();

$user = $_POST['username'];
$pass = $_POST['password'];

$user = preg_replace("/[^a-z0-9_\s-]/", "", $user);
$user = preg_replace("/[\s-]+/", " ", $user);
$user = preg_replace("/[\s_]/", "-", $user);

if(!empty($_POST)){
    if(isset($user) && isset($pass)) {
        $result = mysqli_query($conn, "SELECT * FROM users WHERE username = '$user'");
        if(mysqli_num_rows($result) == 0) {
            $errors[] = 'The username or password are incorrect.';
        } else {
            $passR = mysqli_query($conn, "SELECT * FROM users WHERE username = '$user'");
            while($row = mysqli_fetch_array($passR)){
                $dbHash = $row['password'];
                if(password_verify($pass, $dbHash)){
                    $activeQ = mysqli_query($conn, "SELECT active FROM users WHERE username = '$user'");
                    while($row = mysqli_fetch_array($activeQ)){
                        $active = $row['active'];
                        if($active == 0){
                            $errors[] = 'This user has not activated their account.';
                        } else {
                            $remember_me = ($_POST['remember_me'] == "on") ? 1 : 0;
                            if(isset($_POST['remember_me']) && $remember_me == 1){
                                $_SESSION['user_log'] = time() + 7889238;
                            } else {
                                $_SESSION['user_logi'] = time() + 3600;
                            }
                            $_SESSION['user_id'] = $user;
                            header('location: ./user');
                        }
                    }
                } else {
                    $errors[] = 'The username or password are incorrect.';
                }
            }
        }
    } else {
        header('location: ./');
    }
}

Pretty much, what I would like is:

When the form is submitted, it will push all the data from the form to the login_push.php page, and the PHP on that page will continue to run.

It will query the database and send information back to the original page and if the variable $errors is not empty, it will automatically echo it on the page (echoed on line 6 of the form code block), without refreshing the page. However, if the variable is empty, it will log them in!

All help is appreciated,

Cheers!

EDIT: I have already tested the other code out, however, It did not work the way I would like it to.

GROVER.
  • 4,071
  • 2
  • 19
  • 66
  • why `on('#_js_pdTr2',`??? You can use submit here. – Murad Hasan May 23 '16 at 09:13
  • @FrayneKonok when that specific ID button Is clicked, it will continue out with the Ajax. – GROVER. May 23 '16 at 09:14
  • Possible duplicate of [Call php function from javascript](http://stackoverflow.com/questions/7165395/call-php-function-from-javascript) – David Ansermot May 23 '16 at 09:14
  • @FrayneKonok really? I wanted to be a little more specific with the submission button – GROVER. May 23 '16 at 09:15
  • @David'mArm'Ansermot already looked, didn't work as expected. :/ – GROVER. May 23 '16 at 09:15
  • A couple of things: first, what do you need to happen once the user has been logged in? Because I don't think returning a header() here would do anything since it was an AJAX call. Second, adding on to @FrayneKonok's comment, pretty sure this is incorrect syntax. Try $('#_js_pdTr1').on('submit', function(e) ... or $('#_js_pdTr2').on('click', function(e) ... – irot May 23 '16 at 09:27
  • @irot yeah, I've updated the syntax :) so, when the user credentials are (in fact) correct, I would like it to set a new session, and then send the logged in user to the './user' page. – GROVER. May 23 '16 at 09:35
  • @CaelanGrgurovic okay, so I don't think there's anything wrong with your PHP stuff except instead of returning a `header()`, you should return something like a JSON object and check the status in your JS by appending a `.done(function(data) { ... })` handler to your `.ajax()` call and handling it accordingly (to redirect or not) – irot May 23 '16 at 09:40
  • @irot cheers! um, I'm not really familiar with JSON (at all aha), do you think you could add an answer? :) – GROVER. May 23 '16 at 09:42

1 Answers1

2

Do not use header('location: ./user'); in your ajax. You have some duplicated code, like $result = mysqli_query($conn, "SELECT * FROM users WHERE username = '$user'"); Why do not you call it only once?

You are vulnerable to mysql injection, because you do not escape your variables.

You are set the $username from $_POST and after that you've checked ths isset($_POST), why is it?

Anyway, you need to echo a success / failed, or a JSON object with error and message keys.

$result = [
    'error' => 0,
    'message' => ''
];
//You can do other validations here
if (!empty($_POST)) {

    //Do the dbhash here
    $sql = "SELECT COUNT(*) AS cnt FROM `users` WHERE `username` = '" . mysqli_real_query($conn, $_POST["username"]) . "' AND `password` =  '" . password_verify($_POST['pass'], $dbHash) . "'";
    $res = mysqli_query($conn, $sql);
    $row = mysqli_fetch_row($res);
    if ($row['cnt'] < 1) {
        $result = [
            'error' => 1,
            'message' => 'Bad username or password'
        ];
    }
    //You can add success message if you want
}
echo json_encode($result);

And in your javascript:

$.ajax({
    type: 'post',
    url: 'login_push.php',
    data: $('#_js_pdTr1').serialize(),
    success: function(response) {
        if (response.error != 0) {
            //Show error here
        } else {
           window.location.href = './user'; //Better to use absolute path here
        }
    }
},'json');
vaso123
  • 12,347
  • 4
  • 34
  • 64
  • Thanks! I'll test this out in a sec and get back to you! :) also, I'll have a look into that SQL injection stuff – GROVER. May 23 '16 at 09:58
  • What is `$row['cnt']` for? I don't use this. – GROVER. May 23 '16 at 10:04
  • Also, how am I to output `$errors[]`? And how can I do the password verify? – GROVER. May 23 '16 at 10:06
  • `$row['cnt']` is come from the query: `COUNT(*) AS cnt`. It asks, is there any user with this password? If there is, `COUNT` will return 1. You no need to use my `$result` if you want to use your `errors[]` array, you can. In this case, echo `json_encode($errors);`, and you can iterate through on that array. – vaso123 May 23 '16 at 10:14
  • Ah, ok I kind of get it now! Thank you :) is there any way of still checking if the user is active or not? Still very new to PHP and could use some tips! :) – GROVER. May 23 '16 at 10:26