I have a login form which is validated using javascript and then sent to php file for further processing. Form is submitted via ajax.
Currently, i have an if statement in php file that checks whether form has been submitted, problem is this if statement never evaluates to true. Hence my php code inside my if statement never runs. When request is sent via ajax, .onload event gets invoked without if statement inside php file evaluating to true.
Question
Once the form is submitted to php file via ajax, how can i detect in php file that form has been submitted via javascript.
Here's my php code
<?php
require 'DbConnection.php';
// if form is submitted
if(isset($_POST['login-btn'])) {
$username = $_POST['username-field'];
$password = $_POST['password-field'];
echo '<script>alert(\'form submitted\')</script>';
verifyLoginCredentials($username, $password);
} else {
echo '<script>alert(\'form not submitted\')</script>';
}
// verify admin login credentials
function verifyLoginCredentials($username, $password) {
global $dbConnect;
$query = 'SELECT full_name, username, password FROM admins WHERE username = ?';
$statement = $dbConnect->prepare($query);
if($statement) {
$statement->bind_param('s', $username);
$statement->execute();
$resultSet = $statement->get_result();
// since there will be only one row returned at max, no need of a loop
$row = $resultSet->fetch_assoc();
if($row != null) {
$adminFullName = $row['full_name'];
$adminUsername = $row['username'];
$adminPassword = $row['password'];
// if username/password is correct start session and store
// username, password, full name in the session
if($username === $adminUsername && password_verify($password, $adminPassword)) {
session_start();
$_SESSION['current_admin_fullname'] = $adminFullName;
$_SESSION['current_admin_username'] = $adminUsername;
$_SESSION['current_admin_password'] = $adminPassword;
}
else { // if username/password combination is incorrect
echo 'Incorrect Username/Password Combination';
}
} else { // if username doesn't exists in the database
echo 'Entered username isn\'t registered';
}
} else {
echo 'Error while preparing sql query';
}
}
?>
and here's relevant javascript code
let loginForm = document.querySelector('.login-form');
let usernameField = document.getElementById('username-field');
let passwordField = document.getElementById('password-field');
// submit login form to server using ajax
function ajaxFormSubmit() {
'use strict';
let ajaxRequest = new XMLHttpRequest();
let url = 'admin login.php';
// login form submitted on server successfully
ajaxRequest.onload = function () {
if (ajaxRequest.readyState === 4 && ajaxRequest.status === 200) {
console.log(ajaxRequest.responseText);
displayInfoMessage(ajaxRequest.responseText, 'success');
}
};
// error while login form submission on server
ajaxRequest.onerror = function () {
if (ajaxRequest.status !== 200) {
console.log(ajaxRequest.responseText);
displayInfoMessage(ajaxRequest.responseText, 'error');
}
};
ajaxRequest.open('POST', url, true);
ajaxRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
ajaxRequest.send(new FormData(loginForm));
}
function validateForm(e) {
'use strict';
// prevent form submission
e.preventDefault();
if (anyEmptyField()) {
displayInfoMessage('Please fill all the empty fields', 'error');
highLightEmptyFields();
//return false;
return;
}
// check if username is in right format
if (!(regexTester(/^[A-Za-z0-9_]+$/g, usernameField.value))) {
displayInfoMessage('Username not valid', 'error');
highLightTextField(usernameField);
//return false;
return;
}
// check if username is atleast 3 characters long
if (usernameField.value.length < 3) {
displayInfoMessage('Username should contain atleast 3 characters', 'error');
highLightTextField(usernameField);
//return false;
return;
}
// check if password is in right format
if (!(regexTester(/^[A-Za-z0-9_]+$/g, passwordField.value))) {
displayInfoMessage('Password not valid', 'error');
highLightTextField(passwordField);
//return false;
return;
}
// check if password is atleast 6 characters long
if (passwordField.value.length < 6) {
displayInfoMessage('Password should contain atleast 6 characters', 'error');
highLightTextField(passwordField);
//return false;
return;
}
//return true;
// submit form information to server via ajax
ajaxFormSubmit();
}
// add submit event listener on login form
loginForm.addEventListener('submit', validateForm);
There is no guaranteed way to know that the form was submitted via ajax.
Normally this is done via headers, in our case HTTP_X_REQUESTED_WITH which can be retrieved via the global $_SERVER variable.
Do note that headers can easily be spoofed.
You can check like so:
if(isset($_SERVER['HTTP_X_REQUESTED_WITH']) && !empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest')
{
// code here
}
Here's a few links to look at:
https://paulund.co.uk/use-php-to-detect-an-ajax-request
How to check if the request is an AJAX request with PHP
Related
Okay so i have php code which is supposed to check if there is an existing user in database when login is attempted and send back to javascript fail or success
Php code:
<?php
require_once 'Korisnik.php';
require_once 'dbconn/korisnikdb.php';
if ($_SERVER["REQUEST_METHOD"] === "POST") {
// collect value of input field
$username = $_REQUEST['username'];
$password = $_REQUEST['password'];
$korisnik = getKorisnikByUserPass($username, $password);
if ($korisnik == null) {
$statusArray = array("status"=>"fail");
echo json_encode($statusArray);
return;
} else {
session_start();
$_SESSION["prijavljeniKorisnik"] = $username;
$statusArray = array("status"=>"success");
echo json_encode($statusArray);
return;
}
}
?>
Here i have my javascript code :
$(document).ready(function() {
var usernameInput = $('#usernameInput');
var passwordInput = $('#passwordInput');
var pogresniPodaci = $('#pogresniPodaci');
var praznaPolja = $('#praznaPolja');
pogresniPodaci.hide();
praznaPolja.hide();
$('#submitButton').on('click', function(event) {
var username = usernameInput.val();
var password = passwordInput.val();
console.log(username);
console.log(password);
if (username == '' || password == '') {
praznaPolja.show();
event.preventDefault();
return false;
}
var params = {
'username': username,
'password': password
}
$.post('loginCheck.php', params, function(data) {
console.log(data.status);
if (data.status == 'fail') {
pogresniPodaci.show();
usernameInput.val('');
passwordInput.val('');
return;
}
if (data.status == 'success') {
location.href = 'pocetna';
}
});
event.preventDefault();
return false;
});
});
http://prntscr.com/skb37r -> here you can see status after i press that button
The problem is that php code in loginCheck.php never actually executes, I tried adding echo at start of php file but it doesn't execute.
You are sending http request to localhost. Even if file doesn't exist, your localhost will return status 200, unless it's configured to throw an error.
Try this:
go to http://localhost/loginCheck.php and echo anything there.
echo "This is loginCheck";
If it echoes, you are on the right route to loginCheck file.
If it works, go to browser dev tools > network > and see request headers and find "Request URL" header. it should be "http://localhost/loginCheck.php" - the route to file you visited previously. if its not, you have to fix it in $.post request.
I have a really simple login form that I want to check if the credentials are right (so I don't have to reload a page if the credentials are wrong) before submitting the form.
The problem I'm running into is the response from the AJAX call. When the program decides that the user has supplied the correct credentials, this code works like a charm. In addition, when performing the two checks prior to the AJAX call (whether the user filled in the password input field or if the username is valid), the code works perfectly. It returns an error message and returns the false boolean value, preventing the form from submitting. But, when the response from the server comes back and it is found that the credentials are not correct, the error message displays, but the page also reloads (therein displaying an additional error message). Why is the form still submitting, even though I'm returning false? I've checked the JavaScript console, there are no errors. I've also tried inverting the if statement, checking if ajax.responseText === "true", to the same result. I've tried adding a return false beneath the ajax.onreadystatechange call, but that just prevents the form from submitting at all (regardless of the response from the server).
Here is the form code:
<form method="POST" action="/afton/" onsubmit="return checkForm()">
<label for="username">Username:</label>
<input type='text' id='username' name='username' placeholder='Enter username...' required>
<label for="password">Password:</label>
<input type='password' id='password' name='password' placeholder='Enter password...' required>
<div class="form-buttons">
<button type='submit' name='action' id="loginButton" value='login'>Login</button>
<button type='button' id='register'>Register</button>
</div>
</form>
Here is the js function:
// Function that checks whether the user supplied correct credentials
function checkForm() {
// Get the password provided and the server message div on the page
const messageBox = document.getElementById("server-message");
const password = document.getElementById("password").value;
// If password is blank, return error message and return false
if (password === "") {
messageBox.innerHTML = "<p class='badMessage'>Please fill in the password!</p>"
return false;
}
// If the username input tag doesn't contain the 'goodBorder' class received upon validation of username, return error and false
if (!usernameInput.classList.contains("goodBorder")) {
messageBox.innerHTML = "<p class='badMessage'>Please provide a valid username!</p>"
return false;
}
// AJAX call that posts the info via JSON to check
const ajax = new XMLHttpRequest();
ajax.open("POST", "index.php?action=ajaxLogCheck", true);
ajax.setRequestHeader("Content-type", "application/json");
ajax.send(JSON.stringify({"username":usernameInput.value, "password":password}));
// Handles the AJAX response
ajax.onreadystatechange = function () {
if (ajax.readyState === 4 && ajax.status === 200) {
if (ajax.responseText !== "true") {
messageBox.innerHTML = ajax.responseText;
return false;
}
return true
}
}
}
And here is the PHP code that handles the AJAX:
// Get posted JSON encoded data
$data = json_decode(trim(file_get_contents("php://input")), true);
// Filter and sanitize the supplied username and password
$username = filter_var($data['username'], FILTER_SANITIZE_STRING);
$password = filter_var($data['password'], FILTER_SANITIZE_STRING);
// Get user data by the username and check the username against the password
$userData = getClient($username);
$hashCheck = password_verify($password, $userData['password']);
// Check response from the hashCheck and return the result
if ($hashCheck) {
echo "true";
exit;
}
logAtt($username, $_SERVER['REMOTE_ADDR'], false, getBrowser($_SERVER['HTTP_USER_AGENT']));
sleep(0.5);
$rands = array("Sorry, the username and/or password doesn't match our database. Please try again.", "Sorry, we don't recognize those login credentials. Please try again.", "Sorry, that login was incorrect. Please try again.", "Incorrect, please try again");
$randResult = array_rand(array_flip($rands));
echo "<p class='badMessage'>$randResult</p>";
// Just the point in AJAX function where you were returning True or
// False...Just Assign RESULT = 0 for False and
// RESULT = 1 for True
// .....SUppose You password matches so you were returning True..
// Dont do that...Instead Just Assign RESULT = 0 in that place and
// and out of the ajax Block paste this 'return Boolean(RESULT)'
// if RESULT = 0 then it will return False else it will return True
// Function that checks whether the user supplied correct credentials
function checkForm()
{
// Initialize a Variable Here Say RESULT
var RESULT = 0;
if (password === "")
{
RESULT = 0;
}
else if (!usernameInput.classList.contains("goodBorder"))
{
messageBox.innerHTML = "<p class='badMessage'>Please provide a valid username!</p>"
RESULT = 0;
}
// After this Put the ajax function and if you want to return False
// then simply assign RESULT = 0 instead of 'return false' else assign
// RESULT = 1 instead of 'return true'
return Booelan(RESULT);
// THis line is main Part this is returned by checkForm() function
}
// If I am still not clear, then I'll be happy to explain it on Google Meet.! :)
I am finishing up a form for user registration, and I wanted to know how to clear messages generated dynamically by AJAX, when the user clears the input (backspace). For example, let's say they enter a valid input, but then clear it with all backspaces - my code currently shows the valid input message, but I want that to switch to an empty string / no message when that happens:
if ($nameCheckCount < 1) {
if (preg_match("/^\w+#[a-zA-Z_]+?\.[a-zA-Z]{2,3}$/", $email)) {
echo 'This email is available.';
exit();
} else {
echo 'You entered an email with an invalid format.';
exit();
}
} else {
echo 'This email is taken.';
exit();
}
Is there some way I can change the above code I currently have to clear the message if there is no input after a backspace?
Secondly, once all the input is validated (I have one main HTML file for the form, and then three PHP files to check username, password, and email validity through the use of MySQL, or in the case of the passwords, a simple string match), can I set some sort of flag to then allow the user to submit? For example, the code that checks the email is as such:
function checkEmail() {
"use strict";
var status = document.getElementById("email_status");
var email = document.getElementById("email").value;
if (!(email == "")) {
status.innerHTML = "Checking...";
var request = new XMLHttpRequest();
request.open("POST", "email_check.php", true);
request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
request.onreadystatechange = function() {
if (request.readyState == 4 && request.status == 200) {
status.innerHTML = request.responseText;
}
}
var verify = "emailToCheck=" + email;
request.send(verify);
}
}
This is within my HTML file with the form. Once all fields are validated, is there a way to then allow the user to submit? One user may only have a unique combination of the username and email fields which are stored in the user table along with other data, and no username can be associated with multiple usernames, and vice versa. Thank you in advance for any tips!
Howdie do,
I have a form that simply takes a username and email from a user. The input is sanitiazed via client and on the server side.
The script is sending the POST with no issue and it's returning the data as it should be as I've checked in the log. However, for some reason, the data isn't being displayed in the browser.
Code is below and I feel it's a stupid item I'm overlooking, but I can't find it anywhere
<!DOCTYPE HTML>
<HEAD>
<TITLE>Jeremy's Form Submit Test </TITLE>
<script type="text/javascript" src="js/jquery-1.11.2.js"></script>
<script>
$(document).ready(function()
{
$("#FormSubmit").click(function() //Set click action on formsubmit button
{
var submit = true;
$('#MainForm input[type="text"]').each(function() //Loop through input fields to ensure data is present
{
if($.trim($('#User').val()) == '') //Remove whitespaces and check if field is empty
{
alert('Input can not be blank');
submit = false;
}
var regex = /^[\w-\.]+#([\w-]+\.)+[\w-]{2,4}$/; //RegEx to test email against
if(!regex.test($.trim($('#Email').val()))) //If supplied email without whitespaces doesn't match pattern, then alert user
{
alert('Please provide a valid email');
submit = false;
}
});
if(submit == true) //If data is present, then prepare email and user values to be submitted to .php page
{
data = {'user_name': $('#User').val(), 'email': $('#Email').val()}; //Add username and email to array
$.post("success.php", data, function(ReturnedData) //post data via ajx to success.php and retrieve response
{
console.log(JSON.stringify(ReturnedData));
if(ReturnedData.Type == 'Error') //If error returned, display error message
{
var results = '<h1>'+ReturnedData.Message+'</h1>';
}
else if(ReturnedData.Type == 'Success') //If success returned, display message and remove submit button
{
var results = '<h1>'+ReturnedData.Message+'</h1>';
$('#FormSubmit').remove();
}
$('div#DataHolder').html(results);
}, 'json');
}
});
});
</script>
</HEAD>
<BODY>
<form id="MainForm">
*UserName: <input type="text" id="User" name="FormUsername" required />
*Email: <input type="email" id="Email" name="FormEmail" required />
<input type="submit" id="FormSubmit" value="Submit">
</form>
<div id="DataHolder"></div>
</BODY>
</HTML>
The PHP file is below that returns a json_encoded response and I've confirmed via the console log that the data is being returned properly, but it's not displaying in the div I've set. The log file is showing the correct response, but it's not displaying:
{"Type":"Error","Message":"UserName must be at least 3 characters!!!"}
<?php
if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') //Check apache header to ensure its a json request
{
$ReturnedData = json_encode(array("Type" => "Error", "Message" => "Naughty naughty. This wasn't an ajax request"));
die($ReturnedData);
}
if(isset($_POST)) //Ensure that POST is set
{
//Santiaze the post variables to be double sure no one is up to any funky business
$SaniUser = filter_var($_POST['user_name'],FILTER_SANITIZE_STRING);
$SaniEmail = filter_var($_POST['email'],FILTER_SANITIZE_EMAIL);
//Check that username is at least 3 characters and return error if it's not
if(strlen($SaniUser) != 3)
{
$ReturnedData = json_encode(array("Type" => "Error", "Message" => "UserName must be at least 3 characters!!!"));
die($ReturnedData);
}
//Check that email is a valid email
if(!filter_var($SaniEmail,FILTER_VALIDATE_EMAIL))
{
$ReturnedData = json_encode(array("Type" => "Error", "Message" => "Please supply a valid email address!!!"));
die($ReturnedData);
}
//All variables are good. Return successfully message
$ReturnedData = json_encode(array("Type" => "Success", "Message" => "SUCCESS!!!" .$SaniUser. "Has successfully submitted the form"));
die($ReturnedData);
}
else
{
$ReturnedData = json_encode(array("Type" => "Error", "Message" => "Naughty naughty. No data was submitted!!!"));
die($ReturnedData);
}
?>
WOWOWOW the issue was staring me right in the face.
I didn't initialize var results initially when the data is present. So when I called .html(results), the result variable scope was only in the if/else statement.
Setting the variable at the top of the if statement and then setting the returnedData to that value works
Updated code is below:
if(submit == true) //If data is present, then prepare email and user values to be submitted to .php page
{
var results;
data = {'user_name': $('#User').val(), 'email': $('#Email').val()}; //Add username and email to array
$.post("success.php", data, function(ReturnedData) //post data via ajx to success.php and retrieve response
{
console.log(JSON.stringify(ReturnedData));
if(ReturnedData.Type == 'Error') //If error returned, display error message
{
results = '<h1>'+ReturnedData.Message+'</h1>';
//alert(ReturnedData.Message);
}
else if(ReturnedData.Type == 'Success') //If success returned, display message and remove submit button
{
$('#FormSubmit').hide();
results = '<h1>'+ReturnedData.Message+'</h1>';
}
$('#DataHolder').html(results);
}, 'json');
}
I have been programming a registration form with ajax validation. The way I have it set up is in my js file, I have listeners that fire when the content of the field is changed. They send the data to the server, and the server makes sure it's valid and sends back its response in the form of a JSON object. I then read the values of the JSON object to output potential error messages.
I won't copy and paste the entire files, just one example:
$(document).ready(function() {
// USERNAME VALIDATION LISTENER
$("#regUsername").change(checkName);
}
and then the checkName function looks like this, it sends my ajax request:
function checkName() {
$.ajax({
type: "POST",
url: "./ajax_register.php",
data: {
request: "nameAvail",
username: $("#regUsername").val()
},
success: function(data) { // execute on success
var json = jQuery.parseJSON(data);
if (json.success) { // if usernames do match
$("#usernameAvailiability").removeClass().addClass('match');
$("#usernameAvailiability").text(json.msg);
} else { // if the user has failed to match names
$("#usernameAvailiability").removeClass().addClass('nomatch');
$("#usernameAvailiability").text(json.msg);
}
}
});
}
And depending on the response, it updates a span that tells the user if the input they wrote is valid or not.
The server validates with this part of the php file:
if(!isset($_POST['request'])) { // do nothing if no request was provided
print("no request provided");
} else { //ELSE request has been provided
if ($_POST['request'] == "nameAvail") { // if the request is to check if the username is valid
$response = array("success" => false, "msg" => " ", "request" => "nameAvail");
// CHECK USER NAME AVAILIABILITY CODE
if (!isset($_POST['username']) || empty($_POST['username'])) { // if no username is entered
$response['success'] = false;
$response['msg'] = "No username provided";
} else { // if a username has been entered
$username = $dbConn->real_escape_string($_POST['username']);
if (!ctype_alnum($username)) { // Make sure it's alpha/numeric
$response['success'] = false;
$response['msg'] = "username may only contain alpha numeric characters";
} elseif (strlen($username) < 4) { // make sure it's greater than 3 characters
$response['success'] = false;
$response['msg'] = "username must be at least 4 characters long.";
} elseif (strlen($username) > 20) { // make sure it's less than 26 characters
$response['success'] = false;
$response['msg'] = "username can be up to 20 characters long.";
} else { // make sure it's not already in use
$query = $dbConn->query("SELECT `id`, `username` FROM `users` WHERE `username` = '"
. $username . "' LIMIT 1");
if ($query->num_rows) { // if the query returned a row, the username is taken
$response['success'] = false;
$response['msg'] = "That username is already taken.";
} else { // No one has that username!
$response['success'] = true;
$response['msg'] = "That username is availiable!";
}
}
}
print(json_encode($response));
}
What I'd like to do now is create a function in my javascript for the register button. But I need to make sure all the forms are validated first.
I'm not sure what my options are. What I'd LIKE to do is somehow be able to recycle the code I've already written in my PHP file. I don't want to write out an entirely new if($_POST['request'] == "register") clause and then copy and paste all the validation code to make sure the input is valid before I insert the registrant's data into the database. It seems really repetitive!
I know I could check to see if all the spans on the page were set to 'match', but that could easily be tampered with and blank forms could be submitted.
so far, my register button function looks like this:
function register() {
if ( NEED SOME KIND OF CLAUSE HERE TO CHECK IF ALL THE FIELDS ARE VALID) {
$.ajax({
type: "POST",
url: "./ajax_register.php",
data: {
request: "register",
username: $("#regUsername").val(),
password: $("#regPassword").val(),
email: $("#email").val(),
dob: $("#dob").val(),
sQuest: $("#securityQuestion").val(),
sAns: $("#securityAnswer").val(),
ref: $("#referred").val()
}, success: function(data) {
var json = jQuery.parseJSON(data);
console.log(json);
$("#regValid").removeClass();
$("#regValid").text("");
}
}); //AJAX req done
} else {
$("#regValid").removeClass().addClass('nomatch');
$("#regValid").text("One or more fields are not entered correctly");
}
return false;// so that it wont submit form / refresh page
}
I would really appreciate some help, I've spent the last few hours scouring StackOverflow for an answer, but I can't seem to get anything to work. Will I have to duplicate code in my PHP file or is there a more elegant way to handle this?