I would like to sanitize the form fields before sending the ajax request to increase security. Currently my Javascript code is this:
jQuery(document).ready(function($) {
$('#login-form').submit(function(e) {
e.preventDefault(); // stop the form from submitting the normal way
var form = $(this);
var data = {
'action': 'login',
'username': form.find('#username').val(),
'password': form.find('#password').val(),
'remember': form.find('#remember').val(),
'nonce': form.find('input[name="nonce"]').val()
};
$.ajax({
type: 'POST',
url: '<?php echo admin_url( 'admin-ajax.php' ); ?>',
data: data,
success: function(response) {
if (response.success) {
location.reload();
} else {
$('#login-form-message').html(response.data.message);
}
}
});
});
});
I'm trying to sanitize the input fields like this, I'm a beginner and I'm not entirely sure what I'm doing. Can anyone provide a tip? I appreciate any response, thanks.
var sanitize = require('sanitize-html');
jQuery(document).ready(function($) {
$('#login-form').submit(function(e) {
e.preventDefault(); // stop the form from submitting the normal way
var form = $(this);
var username = sanitize(form.find('#username').val());
var password = sanitize(form.find('#password').val());
var remember = sanitize(form.find('#remember').val());
var nonce = sanitize(form.find('input[name="nonce"]').val());
var data = {
'action': 'login',
'username': username,
'password': password,
'remember': remember,
'nonce': nonce
};
$.ajax({
type: 'POST',
url: '<?php echo admin_url( 'admin-ajax.php' ); ?>',
data: data,
success: function(response) {
if (response.success) {
location.reload();
} else {
$('#login-form-message').html(response.data.message);
}
}
});
});
});
tl;dr: Don't.
By itself, "sanitize" is not a useful term. How you sanitize data depends on:
What you want to protect (protection requirements are different for insertion into a database, an HTML document, an email, and so on).
If you want to do it destructively (discard data that looks like it might be bad) or non-destructively (encode data so special characters don't have their usual special meaning).
You've not told us either of those, so we can't tell you how to handle the data.
However, that doesn't matter because you are asking about doing it on the client.
If you want to protect data before it is inserted into the HTTP request (so the request body can be parsed without errors) then $.ajax does that for you already.
If you want to protect data before your PHP does something with it, then trying to do it on the client is simply wrong since an attacker can bypass your client-side code and submit whatever they want to the server.
Since you must do this on the server, any:
destructive sanitising needs to be replicated (which just introduces the risk of making mistakes).
non-destructive sanitising can't be done because the server would end up double encoding the data which would break it.
Related
I want to know is that possible to send data from one ajax by another ajax or not?
Sounds confusing I know, but here is explanation:
I have payment method where it gets data and handling them by Ajax (unfortunately the creators of this API limited their code a lot) so even if i try to add input request in controller code of that Ajax nothing will work, that's why I need to make another Ajax to handle that input request.
Lets explain more by codes:
controller
public function orderspayonline(Request $request, $id){
error_log('masuk ke snap token dri ajax');
$midtrans = new Midtrans;
//products data + user info etc.
//here magic happens
try
{
$snap_token = $midtrans->getSnapToken($transaction_data);
echo $snap_token;
}
catch (Exception $e)
{
return $e->getMessage;
}
}
If I add anything (I mean anything) in that try{ part it will stop functioning and return error! `even I tried to redirect back my users except echoing token code that gave error as well. So it seems I really don't have any option here but to create new function and Ajax.
JavaScript
<script type="text/javascript">
$('.pay-button').click(function (event) {
$.ajaxSetup({
headers: { 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') }
});
event.preventDefault();
// $(this).attr("disabled", "disabled");
var prdfoId = $(this).data('id');
$.ajax({
url: '{{url("orderspayonline")}}/'+encodeURI(prdfoId),
type: "POST",
cache: false,
success: function(data) {
var resultType = document.getElementById('result-type');
var resultData = document.getElementById('result-data');
function changeResult(type,data){
$("#result-type").val(type);
$("#result-data").val(JSON.stringify(data));
}
snap.pay(data, {
onSuccess: function(result){
changeResult('success', result);
console.log(result.status_message);
console.log(result);
$("#payment-form").submit();
},
onPending: function(result){
changeResult('pending', result);
console.log(result.status_message);
$("#payment-form").submit();
},
onError: function(result){
changeResult('error', result);
console.log(result.status_message);
$("#payment-form").submit();
}
});
}
});
});
</script>
The part I need to manipulate is snap.pay(data, { where results gets back.
Currently they are return in console and disappear in a sec as the result of echo $snap_token; in my controller.
I have tried to get them in hidden input, but as I mentioned I cannot get results because I can't change my try code, even I tried to get them after catch part closed, the same thing happens Error.
Question
How can I get my results in controller?
I need to update my database with that results.
Thanks.
From what I can see you have two choices.
Add another client-side AJAX call within the snap.pay function
Redirect the submission of payment-form towards your own app and then do the onward submission from the server-side.
Option 1:
function serverSubmit(d) {
$.ajaxSetup({
headers: { 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') }
});
$.ajax({
url: '{{url("newroute")}}',
type: "POST",
cache: false,
data: d
});
};
Then amend snap.pay to submit, e.g.
snap.pay(data, {
onSuccess: function(result){
changeResult('success', result);
console.log(result.status_message);
console.log(result);
serverSubmit(result); // <----------
$("#payment-form").submit();
}
...
You may want to encrypt the data if it is sensitive, and you may want to decide not to submit the form if you don't get a successful result from the serverSubmit. You may also want to submit supplemental data beyond the result, but this is a start.
Option 2
Change the <form id="payment-form... action to {{url('newroute')}}
In your controller add a new method and map a post newroute to it.
public function new_method(Request $request)
{
$data = $request->validate(...);
YourModel::create($data); //however you want to save it
$url = 'old_form_submit_URL';
$options = array(
'http' => array(
'header' => "Content-type: application/x-www-form-urlencoded\r\n",
'method' => 'POST',
'content' => http_build_query($data)
)
);
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);
if ($result === FALSE) { /* There was an error */ }
}
In an html button I have this onclick event:
onclick='javascript:updateStatus(59)'
Then I have this function
function updateStatus(){
$.ajax({
type: 'post',
url: '/update-status.php',
success: function(data){
// callback function
}
});
return false;
}
And this is update-status.php
$sql = "UPDATE requests SET status='Closed' WHERE requestid=$requestid";
$updatestatus = mysqli_query($con, $sql);
if (!$updatestatus) {
die("Database query failed: " . mysqli_error($con));
} else {
return "success!";
}
Ultimately, I want the number from the original onclick event (in this example it's 59, but could be any number) to get passed into the $requestid variable in update-status.php.
What is the best/proper way to accomplish this?
Figured out to use "data" in the function after more googling, sorry.
Since you are using the JQuery AJAX function, just use another parameter in the configuration object, data. You're also missing an argument for the function.
function updateStatus(i){
$.ajax({
type: 'post',
data: 'requestid='+i,
url: '/update-status.php',
success: function(data){
// callback function
}
});
return false;
}
You could also create a map and send the map, like so
...
data: {"requestid" : i},
...
You're server side code should be updated though. You don't want to be using input from the client without first sanitizing it. This opens up the threat for SQL Injection attacks.
for example, what if the value of requestid is
1 or '1'='1' --
or
1; drop table requests
First, take the passed in argument in your javascript function and send it to your PHP script like this:
function updateStatus(id){
$.ajax({
type: 'post',
url: '/update-status.php',
data: {id: id},
success: function(data){
}
});
return false;
}
In your PHP access it through $_POST['id']. However, make sure you escape the value to prevent SQL injection attacks.
$requestid = $_POST['id'];
I am developing a website for practice, and I would like to know how to use JS to notify the user that the username he picked is already in use, all works fine, if my function(check_username) returns false, the user succesfully registers himself into the site, otherwise the register won't happen.
When the user can't register I would like to know how can I notify the user with a js script.
<?php
//database includes
include_once('../config/init.php');
include_once('../database/users.php');
if(!check_username($_POST['username'])) {
insertUser($_POST['name'], $_POST['username'], $_POST['email'], $_POST['pass']);
}
else header('Location: ../index.php');
?>
One way would be to change your redirect on failure to a javascript message
else
{
echo "<script>alert('Username already exists');</script>";
}
That's a very trivial example to get you started since you mentioned you're learning JS. You can build a lot of improvements on that.
You can set the returns into a javascript variable and use it to display message if the user is not registered.
var x = <?php echo check_username($_POST['username']); ?>;
if(x) {
alert("You are not registered");
}
You can use php ajax for a live notification to users.
<script>
$(document).ready(function() {
$("#InputFieldID").keyup(function (e) {
//removes spaces from username
$(this).val($(this).val().replace(/\s/g, ''));
//Getting value of input field.
var username = $(this).val();
//Check only if the username characters are above 4
if(username.length >= 4){
$("#IndicatorDivID").html('<p style="color:#ffbf25;">Checking..!</p>');
$.ajax({
type: 'POST',
url: 'check_username.php',
data: {"username": username},
dataType: 'json',
success: function (data) {
if(data.response=='true')
alert("Already Exist");
}
});
}
});
});
//Username Checker
</script>
The result fo check_username.php must be in json format.
eg: {"response":"false"}
I've script two script that i want to merge as one . Script 1 is for checking if email and password is right it brings out a success message "Correct" and it logs you in. Script 2 is what i use to store the email and password in a localstorge
Script 1
$(document).ready(function(){
$("#form1").on('submit',function(event){
event.preventDefault();
data = $(this).serialize();
$.ajax({
type: "POST",
url: "log.asp",
data: data,
success: function(data) {
$('#log_msg').html(data);
var result = $.trim(data);
if(result==="Correct"){
window.location = 'source.asp';
}
}
});
});
});
Script 2
$(function() {
var
$email = $('#email'),
$password = $('#password'),
localEmail = localStorage.getItem("eaddress"),
localPwd = localStorage.getItem("pwd");
// SAVE VARIABLES TO LOCAL STORAGE
$('#form1').on('submit', function() {
localStorage.setItem("eaddress", $email.val());
localStorage.setItem("pwd", $password.val());
});
});
Now i want to merge the two together that it should only save the email and password in the localstorge if the success message is equal
to "Correct" and also logs you in
Never ever store passwords on the client!
Never store passwords unencrypted!
To store the email address in the localStorage you can use this snippet:
$(document).ready(function(){
$("#form1").on('submit',function(event){
event.preventDefault();
var data = $(this).serialize();
$.ajax({
type: "POST",
url: "log.asp",
data: data,
success: function(data) {
$('#log_msg').html(data);
var result = $.trim(data);
if(result==="Correct"){
localStorage.setItem('eaddress', $('#email').val());
}
}
});
});
});
Note: You have to cleanup the localStorage yourself. If you want to store the data for further identification use a sessionId in a cookie or use the sessionStorage for saving temporary data.
Edit: To submit the form after page load you can try something like this:
$(function(){
var eAddr = localStorage.getItem('eaddress');
if (eAddr !== null) {
$('#email').val(eAddr);
$('#form1').trigger('submit');
}
});
Note: If you store the password encrypted on the client and submit it trough the form, the authentication process is quiet insecure.
I think your authentication design is wrong. You should use an authentication cookie (like a session cookie) and validate it on the server side. Without submitting a form every time a page loads nor storing credentials on the client side.
I amc creating A Login script with php and javascript.
What I want to do is log the user in without the page refresh which I have archived so far, With some help from Stack Flow users, I am fairly good with PHP but new to the Javascript client side.
Anyway, When the user enters the correct data and the session gets started how do I get it to call the fade out function?
Heres the PHP Side
<?php
require "../core/database.php";
//lets create some veriables to use, This way is shorter
$username = strip_tags(trim($_POST['user_login']));
$password = strip_tags(trim($_POST['pass_login']));
$md5_pass = md5($_POST['pass_login']);
$user_login = mysql_real_escape_string($username);
$pass_login = mysql_real_escape_string($md5_pass);
if (($user_login) && ($password)) {
//Connect to the database to fetch the users username and password
$select_user = mysql_query("SELECT username,password FROM users WHERE username='$user_login' AND password='$pass_login'");
$user_rows = mysql_fetch_array($select_user);
$username_row = $user_rows['username'];
$password_row = $user_rows['password'];
if(($username_row==$user_login) && ($md5_pass==$password_row)) {
//All user information is correct, Now start the session
//I HAVE CALLED IT HERE HOPING THERE,S A BETTER WAY OF DOING THIS. IT WILL CAL
echo "
Yes, Now we can start the session right here, when your ready.
<script>
$('#field').fadeOut();
</script>";
} else {
echo "The username or password you entered is incorrect";
}
} else {
echo "<b>Blank Fields</b> <br>
You must enter A Username/Password Combination";
}
?>
Incase yous need it, there is the client side aswill (modified by some users to make the functionality better)
$(document).ready(function() {
// Make a function that returns the data, then call it whenever you
// need the current values
function getData() {
return {
user_login: $('#user_login').val(),
pass_login: $('#pass_login').val()
}
}
function loading(e) {
$('#content').html('Loading Data');
}
function check(e) {
e.preventDefault();
$.ajax({
url: 'ajax/check.php',
type: 'post',
data: getData(), // get current values
success: function (data) {
$('#content').html(data);
}
});
}
// Don't repeat so much; use the same function for both handlers
$('#field').keyup(function(e) {
if (e.keyCode == 13) {
var username = $('#user_login').val();
loading(e);
check(e);
}
});
$('#submit').click(function(e) {
if (e.keyCode != 13) {
loading(e);
check(e);
}
});
});
Since PHP is Server Side and Java Script controls the Client side, Probably the best way to do or call it is this way, But its worth A ask anyway.
Besides this everything is working out well.
If you want you can help change the way loading data is coded/works, But the functionality is working perfectly so theres not much need.
The ajax success method needs to check the response from the server to see if login was successful and then take the appropriate action:
// php
if(($username_row==$user_login) && ($md5_pass==$password_row)) {
//All user information is correct, Now start the session
echo 'correct';
} else {
echo 'The username or password you entered is incorrect';
}
// js
function check(e) {
e.preventDefault();
$.ajax({
url: 'ajax/check.php',
type: 'post',
data: getData(), // get current values
success: function (data) {
if (data === 'correct') {
$('#field').fadeOut();
} else {
$('#content').html(data);
}
}
});
}
Returning JSON instead of raw HTML is much more flexible. Quick example:
PHP Side
<?php
require "../core/database.php";
$json = array('success' => false, 'error' => null);
$username = strip_tags(trim($_POST['user_login']));
$password = strip_tags(trim($_POST['pass_login']));
$md5_pass = md5($_POST['pass_login']);
$user_login = mysql_real_escape_string($username);
$pass_login = mysql_real_escape_string($md5_pass);
if (($user_login) && ($password)) {
$select_user = mysql_query("SELECT username,password FROM users WHERE username='$user_login' AND password='$pass_login'");
$user_rows = mysql_fetch_array($select_user);
$username_row = $user_rows['username'];
$password_row = $user_rows['password'];
if(($username_row==$user_login) && ($md5_pass==$password_row)) {
$json['success'] = true;
}
else {
$json['error'] = "The username or password you entered is incorrect";
}
} else {
$json['error'] = "<b>Blank Fields</b> <br>You must enter A Username/Password Combination";
}
echo json_encode($json);
Your AJAX function:
function check(e) {
e.preventDefault();
$.ajax({
url: 'ajax/check.php',
type: 'post',
data: getData(), // get current values
success: function (data) {
var loginResult = JSON.parse(data);
if(loginResult.success){
//Login successful - fade out whatever form or fields
//that you want to
$('#field').fadeOut();
} else{
//Add error message to an error div or whatever
$('#error').html(loginResult.error);
}
}
});
}
I'll start by saying that your PHP should be using the newer mysqli_* functions or the PDO object for all of your database queries. Further, you should be using prepared statements which will safeguard you against SQL injection attacks.
Another thing to note is that in a PHP file that is not going to output anything to the browser, or in other words, is just going to run some code, you don't need a closing tag. In fact, you don't want a closing tag. That is because anything after the closing tag will get sent to the browser, which will get included in the response of your AJAX success function. That includes things like spaces and new lines.
Now, on to your PHP. You are going to want to output some JSON so that you can check for success or failure in your AJAX.
PHP
<?php
require "../core/database.php";
//lets create some veriables to use, This way is shorter
$username = strip_tags(trim($_POST['user_login']));
$password = strip_tags(trim($_POST['pass_login']));
$md5_pass = md5($_POST['pass_login']);
$user_login = mysql_real_escape_string($username);
$pass_login = mysql_real_escape_string($md5_pass);
//Create an array to represent our JSON data.
$json = array(
"successCode" => 0
);
if (($user_login) && ($password)) {
//Connect to the database to fetch the users username and password
$select_user = mysql_query("SELECT username,password FROM users WHERE username='$user_login' AND password='$pass_login'");
$user_rows = mysql_fetch_array($select_user);
$username_row = $user_rows['username'];
$password_row = $user_rows['password'];
if(($username_row==$user_login) && ($md5_pass==$password_row)) {
//All user information is correct, Now start the session
//echo "Yes, Now we can start the session right here, when your ready."
$json['successCode'] = 0;
} else {
//echo "The username or password you entered is incorrect";
$json['successCode'] = 1;
}
} else {
//echo "<b>Blank Fields</b> <br>
//You must enter A Username/Password Combination";
$json['successCode'] = 2;
}
//Set that our content type is JSON
header("Content-type: application/json");
echo json_encode($json); //Convert the PHP array to JSON and echo it as the response.
In our PHP, we have created a $json array which will story the successCode that we will be responding to the client. This will tell the client if the login was a success or failure, and even what type of failure occurred. It will then be up to the client to decide how to display that success or failure to the user. This allows multiple applications to use the same server side source, but display the errors differently if desired.
At the end of the PHP, we have set the header Content-type to specify that we are sending back application/json to the client. Then, we encode the PHP array as JSON, and output it to the response.
jQuery/Javascript
//Let's define different messages depending on what status code we get on the client.
var errorMessages = [
"Yes, Now we can start the session right here, when your ready.",
"The username or password you entered is incorrect",
"<b>Blank Fields</b><br />You must enter A Username/Password Combination"
];
function check(e) {
e.preventDefault();
$.ajax({
url: 'ajax/check.php',
type: 'post',
data: getData(), // get current values
success: function (data) {
//First, make sure that data and data.successCode are defined.
if (data && data.successCode) {
//Here, you are getting back the JSON data from the login call.
$('#content').html(errorMessages[data.successCode]);
//If the successCode is 0, which means it was successful, then we want to fade out the #field div.
if (data.successCode == 0) {
$('#field').fadeOut();
}
} else {
//There must've been a server error. You'd handle that here.
}
}
});
}
Why put the error messages on the client instead of the server? Because it allows you to easily change how the error messages are displayed, without having to touch the server side code. The server just outputs an error code, and the client decides how to handle that code.
The Javascript array, errorMessages, defines the error messages corresponding to their index in the array. The error message at index 0 would correspond to successCode = 0, and so on. If you weren't going to use sequential successCodes, you could use a javascript object to specify keys corresponding to each error code.