I am using secureimage to validate a captcha. I think I am doing things they way they should be done, but I may be missing a big point. I am neither a jQuery guru nor an AJAX guru.
I have a form that passes data to a script to send a thank you email. At the top of the thankYou.php script there is a check against the captcha (using secureimage). It works if I simply submit the form to the PHP. The PHP can properly determine if the captcha is the correct one. If it fails, I can return back to my page. No problems there. What I wanted to do is check the captcha first using AJAX and then if it passes submit the same captcha to the thankYou.php script so I can capture a failed captcha without submitting the form.
I can successfully use AJAX to ask a PHP script if the captcha was correct.
My problem is if I first do the AJAX call and there is a failure, perfect I'm done. If successful, I need to send the captcha to my thankYou.php script to validate before sending the email. Sorry I am long winded. I guess ONE, can I validate the same captcha twice and TWO, if I can't what is a better way to do this? Thanks for whatever suggestions you may have.
PROBLEM SOLVED:
I'm not sure why I did not go straight to this. I am now sending the captcha to the thank you email code via AXAJ. If the captcha fails, I don't send an email and I return an error code. If the captcha is successful, I send the email and return appropriate completion code. Silly I didn't think of this first.
<!-- HTML CODE -->
<form action="ThankYou.php" method="post" id="thankYou">
<img id="captcha" src="securimage/securimage_show.php" alt="CAPTCHA Image" /><br />
Enter Text:<br />
<input type="text" name="captcha_code" size="6" maxlength="6" required />
</span><img src="securimage/images/refresh.png" alt="refresh the Captcha image" height=25 width=25/>
<input type="button" value="submit" class="darkButton" id="contactInfo" onclick="submitTheForm()" />
</form>
/* Javascript Code */
function submitTheForm() {
checkCaptcha(function(data) {
if (data=="true") {
document.getElementById("thankYou").submit();
}
else {
alert("Error");
}
});
}
function checkCaptcha(callBack) {
return $.ajax({
url: 'check_captcha.php',
data: {cc: $( "input[name='captcha_code']" ).val()},
dataType: "json",
type: 'post'
}).done(callBack)
}
/* PHP CODE */
/* thankYou.php */
<?php
session_start();
include_once $_SERVER['DOCUMENT_ROOT'] . '/ACC/securimage/securimage.php';
$securimage = new Securimage();
if ($securimage->check($_POST['captcha_code']) == false) {
$myVariable = "";
foreach($_POST as $key => $value){
$myVariable = $myVariable . $key . "-" . $value . " | ";
}
print($myVariable);
exit;
}
/* check_captcha.php */
<?php
session_start();
include_once $_SERVER['DOCUMENT_ROOT'] . '/ACC/securimage/securimage.php';
$securimage = new Securimage();
if ($securimage->check($_POST['cc']) == false) {
$return = "false";
}
else {
$return = "true";
}
die(json_encode($return));
?>
Related
what the bellow code does is making sure the user isn't allowed to submit a comment unless he's signed in by using $_SESSION['login_user'] supervariable. But it's giving me an error. I think the problem is because I'm calling a javascript function in onsumbit="return(checkUser())". There's something wrong there but I don't know why.
I have the following code:
<script type="text/javascript">
// notice the quotes around the ?php tag
function checkUser() {
<?php
if(isset($_SESSION['login_user'])){
$isExist = true;
}
?>
else{
$isExist= false;
alert( "Please register first!" );
}
var htmlString="<?php echo $isExist; ?>";
return isExist;
}
</script>
...
...
<?php
echo "<form method='POST' onsubmit="return(checkUser());" action='".setComments($connection, $res['post_id'])."'>
//echo "<form method='POST' action='".setComments($connection, $res['post_id'])."'>
<input type='hidden' name='uid' value='".$_SESSION['login_user']."'>
<input type='hidden' name='date' value='".date('Y-m-d H:i:s')."'>
<textarea name='message'> </textarea><br>
<button type='submit' name='commentSubmit'>Comment</button>
</form>";
getComments($connection, $res['post_id']);
?>
....
If this is not the right method to stop the user from submitting a comment, then what could be another method?
In addition to what #RonaldT said, you need to understand that the PHP code is executed on the server before being sent to the browser. So checking for $_SESSION['login_user'] inside a Javascript function is kind of silly, since it will always be the same until the user refreshes the page (only then will PHP re-check the value).
So your function can be simplified like this:
<script type="text/javascript">
// on page load, define a global variable using PHP
var isLoggedIn = <?php echo isset($_SESSION['login_user']) ? "true" : "false"; ?>;
function checkUser() {
// check that global variable every time checkUser() is called in Javascript
if (!isLoggedIn) {
alert( "Please register first!" );
}
return isLoggedIn;
}
</script>
Keep in mind that this kind of "security" is extremely easy to fool (any user can just open their browser console, type isLoggedIn = true; and voila), so be sure to check on the server as well when the form is submitted.
Or better yet: if a user is not allowed to do something, don't give them the opportunity. Why display the form at all if the user will not be allowed to submit it anyway?
<?php
if (!isset($_SESSION['login_user'])) {
echo "Please register to add a comment";
} else {
echo "<form [...everything else...] /form>";
}
getComments($connection, $res['post_id']);
?>
My form kept submitting and then refreshing so I looked at How to prevent page from reloading after form submit - JQuery to figure out how to stop it. The difference in the answer, however, with my solution was that I was submitting the form to itself.
Here's my code:
HTML
<form autocomplete="off" method="post" name="rp">
<input placeholder="Code" type="text" name="code" required>
<button type="submit">Submit</button>
</form>
PHP
<?php
$response = "";
if(isset($_POST['code'])){
echo "<script> alert('test'); </script>";
$password = $_POST["code"];
$result = $connection->query("SELECT * FROM Users WHERE passwords = '$password' LIMIT 1");
if($result->num_rows != 0) {
// unpack object
$data = mysqli_fetch_array($result);
// retrieves user ID (set into a cookie for x amount of time?)
$id = $data["ID"];
mysqli_close($connection);
echo "<script> alert('test 2'); </script>";
$response = "test 2";
header("Location: assessment.php");
} else {
$response = "test 3";
echo "<script> alert('test 3'); </script>";
mysqli_close($connection);
}
}
?>
JS
$("form").submit(function (e) {
// prevent page refresh
e.preventDefault();
var formData = $(this).serialize();
// Make AJAX request
$.post("login.php", formData);
});
I want the form to submit the data but not refresh. What am I doing wrong?
EDIT:
The problem has been narrowed down to the php. Since the request is through javascript, what should the name in the if-statement argument be. It can't be 'rp'.
So I found out something extremely curious. When I changed the if statement to if(isset($_POST['code']){} as some urged me to in the comments and I entered in the correct password, it follows the correct loop and produces this error:
VM1368 jquery.min.js:2 GET http://localhost:8080/assessment 404 (Not Found)
However, it does not produce the alert code I place before the header(). When I put in an incorrect password, it also doesn't do anything (even though I have an else statement). I've updated the php section to include most of the code. The $response variable and the echo/alerts are for debugging.
Final Edit:
Ironically, the reason none of my debugging wasn't working was because the page wasn't refreshing so alerts and variable updates wouldn't happen. (My quest to stop page refresh created all these problems). The solution to my original question was provided by MH2K9 and Toni Michel Caubet in the comment section. Thank you to them and others who tried to help.
Try this :
HTML :
<form autocomplete="off" method="post" name="rp" onsubmit="return false;">
<input placeholder="Code" type="text" name="code" required>
<br>
<button type="submit">Submit</button>
<button id="back_button" type="button"><img src="pics/back_arrow.png">Back</button>
</form>
JS:
$("form").submit(function (e) {
// prevent page refresh
e.preventDefault();
var formData = $(this).serialize();
// Make AJAX request
$.post("login.php", formData , function(data) {
alert(data);
$("form").reset();
});
});
You can alternatively call a function using the onsubmit attribute in HTML.
<form onsubmit='return preventSubmit(e)'>
// form content
</form>
<script>
function preventSubmit(e) {
e.preventDefault()
return false
}
</script>
I'm trying to load a response from the php onto the same page. My Client side html looks like this.
<p>
<script type="text/javascript">// <![CDATA[
function sendForm() {
var dataSend = "?ClientName=" + $("#ClientName").val();
$.post("AddClient.php", dataSend, function(data) {
$("#responseDiv").html(data);
});
// ]]></script>
</p>
<div id="responseDiv"> </div>
<form action="AddClient.php" onsubmit="sendForm()">
<h1>Client Wizard <span>Please fill all the texts in the fields.</span></h1>
<label> <span>Client Name :</span> <input id="ClientName" type="text" name="ClientName" /> </label> <span> </span> <input class="button" type="Submit" value="Send" />
</form>
My Server side php looks like this:
<?php
$dbhost='127.0.0.1';
$dbuser='name';
$dbpass='password';
$dbname='dbname';
$conn=mysqli_connect($dbhost,$dbuser,$dbpass,$dbname);
if(!$conn)
{
die('Could not connect:'.mysqli_connect_error());
}
$client=$_REQUEST["ClientName"];
$retval=mysqli_query($conn,"INSERT into client (clientid,clientname) VALUES (NULL,'$client')");
if(!$retval)
{
die('Could not add client:'.mysql_error());
}
$display_string="<h1>Client Added Successfully</h1>";
echo $display_string;
mysqli_close($conn);
?>
Unfortunately not only is the response being shown in anew html page, Its not accepting any name typed in the form. When I check the sql table the Column has a blank entry under it. I have not been able to figure out where I'm going wrong. Any help would be really appreciated.
All right. Your code have some room for improvement, but it's not an endless thing.
I saw somebody mention sanitization and validation. Alright, we got that. We can go in details here
This is how I will restructure your code using some improvements made by Samuel Cook (thank you!) and added a lot more.
index.html
<p>
<script type="text/javascript">// <![CDATA[
function sendForm() {
var dataSend = {clientName: $('#clientName').val()}
$.post("AddClient.php", dataSend, function(data) {
$('#responseDiv').html(data);
});
return false;
}
//]]>
</script>
</p>
<div id="responseDiv"></div>
<form action="AddClient.php" onsubmit="sendForm(); return false;">
<h1>Client Wizard <span>Please fill all the texts in the fields.</span></h1>
<label><span>Client Name :</span><input id="clientName" type="text" name="clientName"/><span></span><input type="submit" class="button" value="Send"></label>
</form>
Notice change in an input id and input name - it's now start with a lower case and now clientName instead of ClientName. It's look a little bit polished to my aesthetic eye.
You should take note on onsubmit attribute, especially return false. Because you don't prevent default form behavior you get a redirect, and in my case and probably your too, I've got two entries in my table with a empty field for one.
Nice. Let's go to server-side.
addClient.php
<?php
$dbhost = '127.0.0.1';
$dbuser = 'root';
$dbpass = '123';
$dbname = 'dbname';
$conn = mysqli_connect($dbhost, $dbuser, $dbpass, $dbname);
if (!$conn) {
die('Could not connect: ' . mysqli_connect_error());
}
$client=$_REQUEST["clientName"];
$client = filter_var($client, FILTER_SANITIZE_STRING);
if (isset($client)) {
$stmt = $conn->prepare("INSERT into client(clientid, clientname) VALUES (NULL, ?)");
$stmt->bind_param('s', $client);
$stmt->execute();
}
if (!$stmt) {
die('Could not add client:' . $conn->error);
}
$display_string = "<h1>Client $client Added Successfully</h1>";
echo $display_string;
mysqli_close($conn);
?>
That is going on here. We are using PHP filters to sanitize our incoming from somewhere string.
Next, we check if that variable $client even exist (you remember that twice sended form xhr? Double security check!)
Here comes a fun part - to protect our selves even more, we start using prepared mySQL statements. There is no way someone could SQL inject you somehow.
And just check for any errors and display it. Here you go. I've tested it on my machine, so it works.
Forms default behavior is to redirect to the page given in the action attribute (and if it's empty, it refreshes the current page). If you want it to make a request without redirecting to another page, you need to use Javascript to intercept the request.
Here's an example in jQuery:
$('form').on('submit', function(e) {
e.preventDefault(); // This stops the form from doing it's normal behavior
var formData = $(this).serializeArray(); // https://api.jquery.com/serializeArray/
// http://api.jquery.com/jquery.ajax/
$.ajax($(this).attr('action'), {
data: formData,
success: function() {
// Show something on success response (200)
}, error: function() {
// Show something on error response
}, complete: function() {
// success or error is done
}
});
}
Would recommend having a beforeSend state where the user can't hit the submit button more than once (spinner, disabled button, etc.).
First off, you have a syntax error on your sendForm function. It's missing the closing bracket:
function sendForm() {
//...
}
Next, You need to stop the form from submitting to a new page. Using your onsubmit function you can stop this. In order to do so, return false in your function:
function sendForm() {
//...
return false;
}
Next, you aren't actually sending any POST data to your PHP page. Your second argument of your .post method shouldn't be a query string, but rather an object (I've commented out your line of code):
function sendForm() {
var dataSend = {ClientName:$("#ClientName").val()}
//var dataSend = "?ClientName=" + $("#ClientName").val();
$.post("AddClient.php", dataSend, function(data) {
$("#responseDiv").html(data);
});
return false;
}
Lastly, you have got to sanitize your data before you insert it into a database. You're leaving yourself open to a lot of vulnerabilities by not properly escaping your data.
You're almost there, your code just need a few tweaks!
I have managed to get ReCaptcha 2.0 working in my website. However, it's only working when I don't use AJAX and I let the form submit "naturally".
I want to submit the form with the captcha and alert the user with a success note without refreshing the page.
I tried the following code, but it seems like the server doesn't get the user response:
HTML:
<form class="form" action="javascript:void(0)" novalidate>
<!-- all the inputs... -->
<!-- captcha -->
<div class="input-group">
<div class="g-recaptcha" data-sitekey="6LdOPgYTAAAAAE3ltWQGar80KUavaR-JblgPZjDI"></div>
</div>
<div class="errors" id="errors" style="display: none"></div>
<div class="input-group">
<input type="button" value="Send" class="btn-default right" id="submit">
<div class="clear"></div>
</div>
</form>
JS:
$('#submit').click(function(e) {
console.log('clicked submit'); // --> works
var $errors = $('#errors'),
$status = $('#status'),
name = $('#name').val().replace(/<|>/g, ""), // prevent xss
email = $('#email').val().replace(/<|>/g, ""),
msg = $('#message').val().replace(/<|>/g, "");
if (name == '' || email == '' || msg == '') {
valid = false;
errors = "All fields are required.";
}
// pretty sure the problem is here
console.log('captcha response: ' + grecaptcha.getResponse()); // --> captcha response:
if (!errors) {
// hide the errors
$errors.slideUp();
// ajax to the php file to send the mail
$.ajax({
type: "POST",
url: "http://orenurbach.com/assets/sendmail.php",
data: "email=" + email + "&name=" + name + "&msg=" + msg + "&g-recaptcha-response=" + grecaptcha.getResponse()
}).done(function(status) {
if (status == "ok") {
// slide down the "ok" message to the user
$status.text('Thanks! Your message has been sent, and I will contact you soon.');
$status.slideDown();
// clear the form fields
$('#name').val('');
$('#email').val('');
$('#message').val('');
}
});
} else {
$errors.text(errors);
$errors.slideDown();
}
});
PHP:
<?php
// assemble the message from the POST fields
// getting the captcha
$captcha = '';
if (isset($_POST['g-recaptcha-response']))
$captcha = $_POST['g-recaptcha-response'];
echo 'captcha: '.$captcha;
if (!$captcha)
echo 'The captcha has not been checked.';
// handling the captcha and checking if it's ok
$secret = 'MY_SECRET';
$response = json_decode(file_get_contents("https://www.google.com/recaptcha/api/siteverify?secret=".$secret."&response=".$captcha."&remoteip=".$_SERVER['REMOTE_ADDR']), true);
var_dump($response);
// if the captcha is cleared with google, send the mail and echo ok.
if ($response['success'] != false) {
// send the actual mail
#mail($email_to, $subject, $finalMsg);
// the echo goes back to the ajax, so the user can know if everything is ok
echo 'ok';
} else {
echo 'not ok';
}
?>
The result in the PHP page:
captcha: The captcha has not been checked.array(2) { ["success"]=> bool(false) ["error-codes"]=> array(1) { [0]=> string(22) "missing-input-response" } } not ok
Bottom line is, how can I get the input response manually without it automatically going with the rest of the POST data?
Ok, this was pretty silly.
I have done a couple of things wrong:
In the PHP file, all the strings had single quotes on them, and that caused problems.
Throughout the testing, I added multiple printings of things in the PHP file, thus the if (status == "ok") was never working. I did get the emails but did not get any conformation that I did and now I see why.
When I wanted to check what the PHP file was omitting, I simply went to it's address in the URL and always got an error. Even when the mails were sent. Now I understand that that is not the correct way of checking the logs.
Thanks to #Samurai who helped my figure out things.
Final PHP code:
<?php
// assemble the message from the POST fields
// getting the captcha
$captcha = "";
if (isset($_POST["g-recaptcha-response"]))
$captcha = $_POST["g-recaptcha-response"];
if (!$captcha)
echo "not ok";
// handling the captcha and checking if it's ok
$secret = "MY_SECRET";
$response = json_decode(file_get_contents("https://www.google.com/recaptcha/api/siteverify?secret=".$secret."&response=".$captcha."&remoteip=".$_SERVER["REMOTE_ADDR"]), true);
// if the captcha is cleared with google, send the mail and echo ok.
if ($response["success"] != false) {
// send the actual mail
#mail($email_to, $subject, $finalMsg);
// the echo goes back to the ajax, so the user can know if everything is ok
echo "ok";
} else {
echo "not ok";
}
?>
I have a login-form created using HTML that looks like this:
<div class= "form-header">Login</div>
<div class= "error-message" id= "login-error-exists"></div>
<form action= "login.php" method= "POST" onsubmit= "loginCheckIncorrect()">
<div class= "form-field">
<div class= "form-text">
username:
</div>
<input type= "text" class= "login-textbox" id= "login-login-username" name= "loginLoginUsername">
</div>
<div class= "form-field">
<div class= "form-text">
password:
</div>
<input type= "password" class= "login-textbox" id= "login-login-password" name= "loginLoginPassword">
</div>
<input type= "submit" value= "Login" class= "signup-confirm">
</form>
As you can see, its a simple form that is sent to login.php though POST. Upon submitting this form, it calls a JavaScript (using jQuery) function known as loginCheckIncorrect(), which is shown below:
function loginCheckIncorrect() {
"use strict";
var loginLoginUsername = $("#login-login-username").val(), loginLoginPassword = $("#login-login-password");
alert("test1");
$.post('usernameIncorrect.php', {'loginLoginUsername': loginLoginUsername, 'loginLoginPassword': loginLoginPassword}, function (data) {
$("#login-error-exists").html(data);
alert("test2");
event.preventDefault();
return false;
});
alert("test3");
event.preventDefault();
return false;
}
As you can see, this function creates the variables to store the value of username and password entered in each textbox. It sends an alert out (debugging), and then uses a jQuery.post function to send the variables to the PHP file, which I will show below. It then (is supposed to) takes the data sent back from the PHP file to echo into the error div I have in my HTML form.
It then calls an alert (more debugging) and uses a combination of event.preventDefault() and return false to (supposedly) stop the form from submitting. This is repeated after the post function.
This is my PHP code:
<?php
header("X-XSS-Protection: 1");
include("connect.php");
$username = mysqli_real_escape_string($con, $_POST["loginLoginUsername"]);
$password = mysqli_real_escape_string($con, $_POST["loginLoginPassword"]);
echo "<script>alert('test');</script>";
$sql = mysqli_query($con, "SELECT * FROM main WHERE username='$username' and password='$password'");
$count = mysqli_num_rows($sql);
if ($count == 1) {
echo "";
$_SESSION["username"] = $username;
$_SESSION["password"] = $password;
} else {
echo "username and/or password is incorrect.";
}
?>
When I attempt to execute this code, the only alert it displays is test1. Could someone explain to me why this is, and more importantly, how I can fix it? Thanks in advance.
Look at your network requests in your browser's debug panel to see if it's sending what you think it is, put some debug statements in your PHP to see what is and isn't getting hit.
In this case, I think you might be missing the .val() on $('login-login-password') just before the alert("test1") in your javascript.
There is no event defined. That would be a problem and the form will submit. And the preventDefault in the callback is useless since the function already finished.
1) The name of the php file is login.php
2) The url to which you are requesting the post is usernameIncorrect.php
Therefore:
$.post('login.php', {'loginLoginUsername': loginLoginUsername, 'loginLoginPassword': loginLoginPassword}, function (data) {
$("#login-error-exists").html(data);
alert("test2");
event.preventDefault();
return false;
});
Alert test1 is the only one appearing because the post fails.
Probably with a fail event you would have cached the error.
Try, if you want to test that:
$.post('wrongUrl.php', {'loginLoginUsername': loginLoginUsername, 'loginLoginPassword': loginLoginPassword}, function (data) {
$("#login-error-exists").html(data);
alert("test2");
event.preventDefault();
return false;
})
.fail(function() {
alert( "error" );
});