I am looking for a secure way of passing sensitive variables to a php file via ajax. At the moment i have been using data attributes but the values can be changed using something like firebug.
HTML:
<div class="strip">
<?php
if($hide == 0) {
echo '<h2 class="action" data-type="1" data-id="<?php echo $id; ?>" data-action="0">Hide Business</h2>';
}
if($hide == 1) {
echo '<h2 class="action" data-type="1" data-id="<?php echo $id; ?>" data-action="1">Un-Hide Business</h2>';
}
?>
<h2 class="action" data-type="1" data-id="<?php echo $id; ?>" data-action="2">Delete Business</h2>
</div>
JavaScript/JQuery:
$(".action").click(function() {
var type = $(this).data("type");
var id = $(this).data("id");
var action = $(this).data("action");
$.ajax({
url : 'assets/php/confirm.php',
type : 'POST',
data : "type="+type+"&action="+action+"&ids="+id,
success : function (result) {
alert(result);
}
});
});
PHP:
if(isset($_POST['type'], $_POST['action'], $_POST['ids'])) {
$type = $_POST['type'];
$action = $_POST['action'];
$ids = explode(",", $_POST['ids']);
$count = count($ids);
if($type == 0) {
if($action == 1) {
$stmt = $mysqli->prepare("DELETE FROM deals WHERE id=?");
} else {
$stmt = $mysqli->prepare("UPDATE deals SET hide=0 WHERE id=?");
}
} else {
if($action == 1) {
$stmt = $mysqli->prepare("DELETE FROM businesses WHERE id=?");
} else {
$stmt = $mysqli->prepare("UPDATE businesses SET hide=0 WHERE id=?");
}
}
for($i = 0; $i < $count; $i++) {
$stmt->bind_param('s', $ids[$i]);
$stmt->execute();
$stmt->close();
}
echo 'Success updated '.$_POST['ids'];
}
The variables that need to be secure are the data-type, data-id, data-action values. Reason being i dont want the wrong database entries being deleted.
I dont know of any alternatives, so any help would be great.
If you want to stop the user changing them, then you can't get them from the user at all. Store the data on the server instead.
If you want to limit what values you'll accept from the user, then limit them on the server. Perform authentication and authorization. Make sure the values being changed are ones the logged in user is allowed to change.
As your code on the client - inside the browser - can not be hidden, you should secure the connection between client and web server - use SSL/TSL for that...
Related
I'm currently working on a Facebook like chat, with 3 different chat boxes that should work simultaneously. I can send and read messages from my database, but I'm having difficulty displaying this information in the right place. In chat.php I have this snippet of code:
$.ajax({
url: "fetch_user_chat_history.php",
method: "POST",
data: jQuery.param({receiver_id:receiver_id, num:num}),
success: function(data) {
$('$chat_history_'+receiver_id).html(data);
}
});
Now I am able to read the data from my database correctly in fetch_user_chat_history.php, but when I iterate over my messages I'm unable to output them correctly back to chat.php. Here is my fetch_user_chat_history.php:
<?php
include "opendb.php";
session_start();
$output1 = '';
$output2 = '';
$increment = 0;
$sender = $_SESSION['user_id'];
$receiver_id = $_POST['receiver_id'];
$chatboxnum = $_POST['num'];
$query = 'SELECT content, timestamp_chat, sender_id FROM messages WHERE (sender_id = '.$sender.' AND receiver_id = '.$receiver_id.' OR (sender_id = '.$receiver_id.' AND receiver_id = '.$sender.'))';
$statement = $db->prepare($query);
$statement->execute();
$result = $statement->fetchAll(PDO::FETCH_ASSOC);
switch ($chatboxnum) {
case 1:
foreach ($result as $row) {
if ($row['sender_id']==$sender) {
echo '<script>var para = document.createElement("div");';
echo 'para.innerHTML = '.$row["content"].';';
echo 'var att = document.createAttribute("class");';
echo 'att.value = "msg-send";';
echo 'para.setAttributeNode(att);';
echo 'document.getElementById("sendbox-1").appendChild(para);';
echo 'document.body.appendChild(para); </script>';
}
else {
echo "var element = document.getElementById('receivebox-1'); element.classList.add('msg-receive');";
}
$increment += 1;
}
break;
}
?>
None of my echo statements add anything to chat.php. I'm sure there's a very easy fix as I have done this before but I can't seem to get it working. I apologise for the long post.
I've created a search page that sends results to a table with the ability to click on a specific record which then opens another page in the desired format.
I'd like to do is be able to open different formatted pages based on the data returned in the search query but I'm having a bit of trouble pulling it all together.
Here's the PHP used to request and retrieve the data from the database, as well as populate it in a table where each record can be selected and used to populate a planner page with all the proper formatting:
$search = $_POST['search'].'%';
$ment = $_POST['ment'];
$stmt = $link->prepare("SELECT lname, fname, rank, reserve, ment1, pkey FROM planner WHERE lname LIKE ? AND ment1 LIKE ? ORDER BY lname, fname");
$stmt->bind_param('ss', $search, $ment);
$stmt->execute();
$result = $stmt->get_result();
if ($result->num_rows > 0) {
echo "<table><tr><th>Last Name</th><th>First Name</th><th>Rank</th><th>Mentor Group</th><th></th></tr>";
while($row = $result->fetch_assoc()) {
$rsv = $row['reserve'];
$pkey = $row['pkey'];
echo "<tr><td>".$row['lname']."</td><td>".$row['fname']."</td><td>".$row['rank']."</td><td>".$row['ment1']."</td><td><button onClick=getPlanner('".$pkey."');>Get Planner</button></td></tr>";
}
echo "</table>";
} else {
echo "0 results";
}
Now the fun part. I want to open different pages based on the information contained in the record. I've got it working for the pkey variable by itself with a single javascript function. However, if I want to open a differently formatted page using the same function using if, else statements, the table only populates with the link page based on the last record compared. Here is my attempt to get the JavaScript with the if, else statements working but it only uses the format of the last record that's compared.
var pkey = <?php echo json_encode($pkey); ?>;
var rsv = <?php echo $rsv ?>;
//var check = document.write(rsv);
function getPlanner(pkey) {
if(rsv != 0){
var plan = window.open("../php/plannerR.php?pln=" + pkey);
} else {
var plan = window.open("../php/planner.php?pln=" + pkey);
}
}
How do I get the 'Get Planner' button to open the correctly formatted planner page based on the users specific information?
To make things easier I'd suggest the following:
Do the logic already in php when generating the html-table (and the link).
while($row = $result->fetch_assoc()) {
$rsv = $row['reserve'];
$pkey = $row['pkey'];
if($rsv) { // thats basicly the same as !=0
$target='../php/plannerR.php'
} else {
$target='../php/planner.php'
}
echo "<tr><td>".$row['lname']."</td><td>".$row['fname']."</td>";
echo "<td>".$row['rank']."</td><td>".$row['ment1']."</td>";
echo "<td><a class='button styleIt' href='".$target."?pkey=".$pkey."&rsv=".$rsv."'>Get Planner</a></td></tr>";
}
If you wanna stick to your js solution (which is more hassle unless you really need it) you can of course go with the solution from my comments that you already successfully implemented (and posted as answer so others can see the implementetion).
Thanks to Jeff I played around a bit with bringing both variables into the function and got it to work. Final code below.
$search = $_POST['search'].'%';
$ment = $_POST['ment'];
$stmt = $link->prepare("SELECT lname, fname, rank, reserve, ment1, pkey FROM planner WHERE lname LIKE ? AND ment1 LIKE ? ORDER BY lname, fname");
$stmt->bind_param('ss', $search, $ment);
$stmt->execute();
$result = $stmt->get_result();
if ($result->num_rows > 0) {
echo "<table><tr><th>Last Name</th><th>First Name</th><th>Rank</th><th>Mentor Group</th><th></th></tr>";
while($row = $result->fetch_assoc()) {
$rsv = $row['reserve'];
$pkey = $row['pkey'];
echo "<tr><td>".$row['lname']."</td><td>".$row['fname']."</td><td>".$row['rank']."</td><td>".$row['ment1']."</td><td><button onClick=getPlanner('".$pkey."','".$rsv."');>Get Planner</button></td></tr>";
}
echo "</table>";
} else {
echo "0 results";
}
var pkey = <?php echo json_encode($pkey); ?>;
var rsv = <?php echo $rsv ?>;
//var check = document.write(rsv);
function getPlanner(pkey, rsv) {
if(rsv != 0){
var plan = window.open("../php/plannerR.php?pln=" + pkey);
}
else{
var plan = window.open("../php/planner.php?pln=" + pkey);
}
}
What is wrong here?
My PHP/HTML (The only part that matters):
if(isset($_POST['submit']))
{
$date = date('Y-m-d', strtotime(str_replace("-","/",$_POST['dateOfEntry'])));
$username = $_POST['user'];
$query = 'SELECT `ID`, `Date`, `Description`, `TypeOfDowntime`, `Machine#` FROM `machineissuesreport` WHERE `Date`="'.$date.'" AND `UpdatedBy` = "'.$username.'" ORDER BY `ID` DESC';
$conn = mysqli_query($connection, $query);
while($row = mysqli_fetch_array($conn))
{
echo '<tr>';
echo '<td style="text-align: center" width="5px"><input type="button" name="edit" value="Edit"></td>';
echo '<td style="text-align: center" width="5px">Delete</td>';
echo '<td style="display: none;"><input type="hidden" value='.$row['ID'].'></td>';
echo '<td>'.$row['Date'].'</td>';
echo '<td>'.$row['Description'].'</td>';
echo '<td>'.$row['TypeOfDowntime'].'</td>';
echo '<td>'.$row['Machine#'].'</td>';
echo '</tr>';
}
}
?>
My Ajax/Javascript:
$(document).ready(function()
{
$('.delete').click(function()
{
if(confirm("Are you sure you want to delete this row?"))
{
var del_id = $(this).attr('id');
var $ele = $(this).parent().parent();
$.ajax({
type: 'POST',
url: 'machineEntryLogEdit.php',
data: {'del_id':'del_id'},
success: function(data)
{
$ele.fadeOut().remove();
},
error: function (xhr, status, error)
{
alert(this);
}
});
}
});
});
My PHP (on an external script: machineEntryLogEdit.php):
include('connServer.php');
$deleteID = $_POST['del_id'];
$query = 'DELETE FROM `machineissuesreport` WHERE `ID` ="'.$deleteID.'"';
$result = mysqli_connect($connection, $query);
if(isset($result))
{
echo "YES";
}
else
{
echo "NO";
}
?>
I have searched around and around for solutions but no avail. The only things it does is delete the record from the HTML table, but not from the database, causing the supposed-to-be-deleted row to reappear after refresh. I am still very new to AJAX (in fact I just learned it myself today) and still reading the documentations and forums. Thanks.
This should be data: {'del_id': del_id} remove quotes so it react as a variable, not just a single string. And one more thing, your delete query does not execute cause you're using :
$result = mysqli_connect($connection, $query);
Should be mysqli_query like the one you did on selecting data's part:
$query = 'DELETE FROM `machineissuesreport` WHERE `ID` ="'.$deleteID.'"';
$result = mysqli_query($connection, $query);
It looks to me like you didn't pass the submit variable in your data. If you want to include a form you need to pass the data, right now the server is receiving only one parameter, del_id
I am displaying posts in a table and then trying to call more posts using ajax, but I am encountering problems here, on clicking show more same posts appear again so how to call next posts by id, and another problem is on clicking show more it changes to loading and remains their, I want it to hide after posts have been loaded.
I am calling the whole table again I think I would be better to call only rows. Here are my two files
index.php
<script type="text/javascript">
$(document).ready(function(){
$(document).on('click','.show_more',function(){
var ID = $(this).attr('id');
$('.show_more').hide();
$('.loding').show();
$.ajax({
type:'POST',
url:'ajax_more.php',
data:'id='+ID,
success:function(html){
$('#show_more_main'+ID).remove();
$('#posts').append(html);
}
});
});
});
</script>
$sql = "SELECT * FROM posts order by id desc limit 6";
$query = $db->prepare($sql);
$query->execute();
$row = $query->fetch(PDO::FETCH_ASSOC);
$ID = $row['id'];
<div id="posts">
<table>
<tr>
<?php do { //horizontal looper?>
<td>
<div>id</div>
<div>title</div>
<div>body</div>
<div>date</div>
</td>
<?php
$row = $query->fetch(PDO::FETCH_ASSOC);
if (!isset($nested_List)) {
$nested_List= 1;
}
if (isset($row) && is_array($row) && $nested_List++%3==0) {
echo "</tr><tr>";
}
} while ($row); //end horizontal looper
?>
</table>
<div class="show_more_main" id="show_more_main<?php echo $ID; ?>">
<span id="<?php echo $ID; ?>" class="show_more" title="Load more posts">Show more</span>
<span class="loding" style="display: none;"><span class="loding_txt">Loading…</span></span>
</div>
</div>
ajax_more.php
<?php
include('db.php');
if(isset($_POST["id"]) && !empty($_POST["id"])){
$sql = "SELECT * FROM posts order by id desc limit 6";
$query = $db->prepare($sql);
$query->execute();
$row = $query->fetch(PDO::FETCH_ASSOC);
$ID = $row['id'];
?>
<table>
<tr>
<?php do { //horizontal looper?>
<td>
<div>id</div>
<div>title</div>
<div>body</div>
<div>date</div>
</td>
<?php
$row = $query->fetch(PDO::FETCH_ASSOC);
if (!isset($nested_List)) {
$nested_List= 1;
}
if (isset($row) && is_array($row) && $nested_List++%3==0) {
echo "</tr><tr>";
}
} while ($row); //end horizontal looper
?>
</table>
<div class="show_more_main" id="show_more_main<?php echo $ID; ?>">
<span id="<?php echo $ID; ?>" class="show_more" title="Load more posts">Show more</span>
<span class="loding" style="display: none;"><span class="loding_txt">Loading…</span></span>
</div>
<?php
}
?>
You will have to use OFFSET and LIMIT for your SQL Query. Currently you are using SELECT * FROM posts order by id desc limit 6. That isn't going to load you "more", as it will always only fetch the 6 biggest posts (ordered descending by their id).
You have a couple of problems.
When your AJAX call completes and you want the loading message to disappear, you need to hide that in your success callback of the ajax call. Like so:
$(document).on('click','.show_more',function(){
var ID = $(this).attr('id');
$('.show_more').hide();
$('.loding').show();
$.ajax({
type:'POST',
url:'ajax_more.php',
data:'id='+ID,
success:function(html){
$('#show_more_main'+ID).remove();
$('#posts').append(html);
$('.loding').hide();
}
});
});
In your SQL, you aren't doing anything to select alternative posts because after checking if the ID was sent. You don't do anything with it. Change your SQL to select id's greater than it if it exists.
$postedId = (int)$_POST['id'];
$sql = "SELECT * FROM posts order by id desc WHERE id > $postedId limit 6";
You want to make sure that the id is escaped to prevent any sort of SQL injection. So as a simple measure, I converted it to an integer (I am assuming on that). Otherwise, you should look into using prepared statements for your queries to prevent SQL injection. http://php.net/manual/en/mysqli.quickstart.prepared-statements.php
Your SQL query needs to be fixed. Lets say you want to load the next 6 (ordered in descending order by ID). To do this, you should send some kind of variable like offset. Then you can say:
$sql = "SELECT * FROM posts ORDER BY id DESC LIMIT $offset, $end;"
Where $end = $offset + 6;
Before using this, though, be sure to check that $offset is numeric to prevent SQL injection. This could be implemented using:
if(i!sset($_POST["id"]) || empty($_POST["id"])){
die("No ID value present.");
}
$offset = (isset($_POST['offset']) ? $_POST['offset'] : 0);
if(!is_numeric($offset)){
die("Abnormal input detected.");
} else {
// Input is numeric
$offset = intval($offset);
}
$end = $offset + 6;
$sql = "SELECT * FROM posts ORDER BY id DESC LIMIT $offset, $end;"
/* Your code for actually querying the DB and processing results */
Note: I'm not too familiar with PDO, however, this should be compatible with PDO and safe/secure to use.
i am trying to modify a session variable in each ajax call (so as to later retreive only the new content from db ) but one session variable $_SESSION['s'] is getting unset in every alt. ajax call ! however the unmodified session variable $_SESSION["iuser"] is working fine . I am testing this on localhost / wamp and coding in npp .
<?php
session_start();
//if(isset($_SESSION["s"]))
$in=$_SESSION["s"];
//echo $_SESSION['sid'];
$link=mysql_connect("localhost","root","");
mysql_select_db("secure_scrapbook") or die("Sorry :( Connection Error");
$query="Select data,user,id from public where public=1 && id>'$in' ORDER BY id DESC";
$result=mysql_query($query);
$i=mysql_fetch_array($result);
$_SESSION["s"]=$i["id"];
//echo $_SESSION['sid'];
if(!($_SESSION["s"]==$in))
{echo 0;
echo $in;
echo $_SESSION["iuser"];
echo $_SESSION["s"];
echo "check<br>";
}
?>
--jquery /ajax -----
<script>
setInterval(function() {
$.ajax({
url: "gets.php",
type : "get" ,
dataType : 'html',
success : function(data){
//$("#public").html(data);}
$("#public").html(data+$("#public").html()+'-');}
});}, 5000); //5 seconds
</script>
May I suggest you debug your calls like this:
<?php
session_start();
if (empty($_SESSION["s"])){
echo 'EMPTY SESSION ';
die;
}
$in = $_SESSION["s"];
$link=mysql_connect("localhost","root","");
mysql_select_db("secure_scrapbook") or die("Sorry :( Connection Error");
$query="Select data,user,id from public where public=1 && id>'$in' ORDER BY id DESC";
$result=mysql_query($query);
$i=mysql_fetch_array($result);
if (empty($i["id"])){
echo 'EMPTY $i';
die;
}
$_SESSION["s"]=$i["id"];
//echo $_SESSION['sid'];
if(!($_SESSION["s"]==$in))
{echo 0;
echo $in;
echo $_SESSION["iuser"];
echo $_SESSION["s"];
echo "check<br>";
}
?>
Each time you get the message EMPTY SESSION or EMPTY $i check:
the ajax headers and try to step-by-step track your problem.
the element in the database does have an ID
the $in is within the boundries of possible ID's
the $in is a number
<?php
session_start();
//if(isset($_SESSION["s"]))
$in=$_SESSION["s"];
//echo $_SESSION['sid'];
$link=mysql_connect("localhost","root","");
mysql_select_db("secure_scrapbook") or die("Sorry :( Connection Error");
$query="Select data,user,id from public where public=1 && id>'$in' ORDER BY id DESC";
$result=mysql_query($query);
if($i=mysql_fetch_array($result))
{
$_SESSION["s"]=$i["id"];
//echo $_SESSION['sid'];
if(!($_SESSION["s"]==$in))
{
echo 0;
echo $in;
echo $_SESSION["iuser"];
echo $_SESSION["s"];
echo "check<br>";
}
}
else
echo "No more Data in table";
?>
Try this and if "No more Data in table" is echoed, it means that your db doesn't have any data satisfying the conditions you set.
One more thing, seeing your code it looks like $_SESSION["s"] will never be equal to $in so i guess you don't need to use the if condition.