Protect a page from external access outside the server - javascript

In a backend panel, in order to populate a datatable, I echo the records in a php page in format JSON, then I parse, format and populate the datatable with JS.
The issue is, how do I prevent peoples from accessing that php page and leaking all the informations?
This is what my code look like:
var options = {
data: {
type: 'remote',
source: {
read: {
url: 'http://127.0.0.1/inc/phpscripts/printinfo.php',
},
},
pageSize: 10,
serverPaging: false,
serverFiltering: false,
serverSorting: false,
},
layout: {
scroll: false,
footer: false
},
sortable: true,
pagination: true,
columns: [{
field: 'id',
title: '#',
sortable: false,
width: 20,
selector: {
class: ''
},
textAlign: 'center',
}, {
field: 'name',
title: 'name',
}, {
field: 'surname',
title: 'surname',
}, {
field: 'address',
title: 'address',
}, {
field: 'phone',
title: 'phone',
},
}],
};
This is the code of the printinfo.php
function datatable($userid){
global $conn;
$total = totalrows($userid);
$pagination = ceil($total/10);
echo '{
"meta": {
"page": 1,
"pages": '.$pagination.',
"perpage": 10,
"total": '.$total.',
"sort": "desc",
"field": "name"
},
"data":';
$rows = array();
$query = $conn->prepare('SELECT * FROM table WHERE id = ? ORDER BY name DESC');
$query->bind_param('i', $userid);
if (!$query->execute());
$res = $query->get_result();
$counter = 0;
//$rows = array();
while ($data = $res->fetch_assoc()) {
$rows[] = $data;
}
print json_encode($rows);
echo '}';
}
datatable(SESSION['id']);
While this is the display content of printinfo.php
{ "meta": { "page": 1, "pages": 1, "perpage": 10, "total": 4, "sort": "desc", "field": "level" }, "data":
[{"id":1,"name":"frank","surname":"blank","address":"st andrew","phone":"+1555484845"},
{"id":1,"name":"andrew","surname":"blank","address":"st paroli","phone":"+1555895685"}]}
It works fine, but I don't think this is secure at all.
So, how would you approach it in order to secure the datas?

You should build some authentication scheme, in order to validate the identity of user that fetches your data.
A simple example (not secure at all, but shows the goal) - send some identification code as post request to that php script and validate it there.
Better security can be achieved by creating a database with hashed or encrypted passwords and validating the user at sign in stage. After that validation, you can store some credentials on the server and check in your php script the identity.
Again, this is not so simple as described and should be done carefully.

Related

Send more values via URL

I am using Datatable plug-in to print values from database.
I get results and it prints in table. Now I am having trouble with sending values to the other file. Values that I need to send are userID, all titles of column except for last title, and two other variables which contains date.
When I click on '', beside data that contains userId, I need to send "User, Work time, Additions, Business, Break" as well as two variables printed below.
Other two variables are:
var date1 = "2017-01-01";
var date2 = "2017-02-28";
$('#myData').DataTable( {
data: dataSet,
fixedHeader: true,
responsive: true,
"columns": [
{ title: "User", data: "ime"},
{ title: "Work time", data: "Rad" },
{ title: "Additions", data: "Privatno" },
{ title: "Business", data: "Poslovno" },
{ title: "Break", data: "Pauza" },
{
"title": '<i class="icon-file-plus"></i>',
"data": "userID",
"render": function (data) {
return '' + '<i class="icon-file-plus"></i>' + '';
}, "width": "1%",
}
]
,"columnDefs": [ { "defaultContent": "-", "targets": "_all" },{ className: "dt-body-center", "targets": [ 5 ] } ]
});
Any help or advice is appreciated, I am stuck here.

How can I load rows in JsGrid table that got from php file?

I tried to load rows of data from a table in MySQL. I used jsgrid with PHP.
My two php files connect to the localhost datanase and select rows from the tables using mysqli functions, and copy the result of the query into an array and send by json_encode() to an HTML file where I put the jsgrid code.
Then, I call the html file into other PHP file by <iframe> html tag.
The names of PHP files are:
newsConf, controll and getnewscat
HTML file: basic.html
in controll.php:
public function newsConfig(){
$this->CONN = new Conn();//class from external page to connect DB
try{
$dfnet = $this->CONN->open_connect();
$qnco = mysqli_query($dfnet,"select * from category");
if(!$qnco) return "";
else{
while($qncoarray = mysqli_fetch_row($qnco)){
//here I try copy rows into array
$nnopCo[] = array(
'ID' => $qncoarray['ID'],
'Name' => $qncoarray['Name']
);
}
return $nnopCo;
}
$this->CONN->close_connect($dfnet);
}
catch(Exception $er){
}
in getnewscat.php:
<?php require_once "../../bin/controll.php";
$db_controll = new Controll();
$cat_news = new ArrayObject($db_controll->newsConfig());
header('Content-type: application/json');
echo json_encode($cat_news->getArrayCopy());
?>
in basic.html: is the same file from jsgrid demo, but I change the code in javascript and canceled the db.js file
$(function() {
$("#jsGrid").jsGrid({
height: "70%",
width: "50%",//100%
selecting: false,
filtering: false,
editing: false,
sorting: false,
paging: true,
autoload: true,
pageSize: 15,
pageButtonCount: 5,
controller: {
loadData: function(clients){
var d = $.Deferred();
$.ajax({url: "../bin/getnewscat.php", dataType: "json",function(obj){
for (var i = 0; i < obj.length; i++) {
/*res[i]=data.i;
i++;*/
clients = {
"ID": obj.ID,
"Name": obj.Name
};
}
}
}).done(function(response) {
d.resolve(response.value);
});
return d.promise();
}
In newsConf.php: that file should call basic.html and give the result
by this:
<iframe name="demo" src="jsgrid-1.2.0/demos/basic.html"></iframe>
But the result is empty and I don't know why?, however I change the code but it didn't yield success.
What have I missed here?
Update
See my update below.
The done function should work. Remove success handler and put your mapping into done handler. Then put a debugger into done handler to ensure what you get in a response. Then map the response accordingly and resolve the deferred.
loadData: function(clients){
var d = $.Deferred();
$.ajax({
url: "../bin/getnewscat.php"
}).done(function(response) {
// put a debugger here to ensure that your response have 'value' field
var clients = $.map(response.value, function(item) {
return {
ID: item.SomeID,
Name: item.SomeName
};
});
d.resolve(clients);
});
return d.promise();
}
I'm not sure whether you need a mapping or not. Maybe you can remove it in the end. But do everything in the done handler and check the format of the response.
Sorry for my delay, but I think I got where's my mistake!
I fixed it and I got what I missed,
In controll.php file, I used mysqli_fetch_row() function, but I forgot I send the data in a named array, so I changed it to mysqli_fetch_assoc() function.
and about basic.html I changed it to:
<script>
$(function() {
{
$("#jsGrid").jsGrid({
height: "70%",
width: "50%",//100%
selecting: false,
filtering: false,
editing: false,
sorting: false,
paging: true,
autoload: true,
pageSize: 15,
pageButtonCount: 5,
controller: {
loadData: function(filter) {
//here how I fix it!
return $.ajax({url: "../bin/getnewscat.php",data:filter
});
}
},
////////////////////////////////////////////////////////////
fields: [
{ name: "ID", type: "number", width: 50 },
{ name: "Name", type: "text", width: 50},
{ type: "control", modeSwitchButton: false, deleteButton: false }
]
});
$(".config-panel input[type=checkbox]").on("click", function() {
var $cb = $(this);
$("#jsGrid").jsGrid("option", $cb.attr("id"), $cb.is(":checked"));
});
});
</script>
but I think it's not secure, how could I make it more secure?
I was having the same issue. However once I added the return to $.ajax line all I get is blank lines but the grid is trying to render something. See image below.
PHP Code Below:
$sql = "SELECT e.estimateid, e.customerid, e.compid, cu.first_name,cu.last_name,e.reference_num, e.estimate_date, e.expiry_date, e.hours, e.sales_person, e.project_name
FROM estimates AS e INNER JOIN company AS c ON e.compid = c.compid
INNER JOIN customers AS cu ON e.customerid = cu.customerid";
$resultsE = $conn->query($sql);
$rows = array();
while ($r = $resultsE->fetch_assoc()){
$rows[] = $r;
}
$data = array($rows);
}
//header("Content-Type: application/json"); //If I uncomment this line the Grid says No Results.
echo json_encode($data);
JS Code Below:
$(function() {
$("#jsGrid").jsGrid({
height: "90%",
width: "98%",
filtering: true,
inserting: false,
editing: false,
sorting: true,
paging: true,
autoload: true,
pageSize: 10,
pageButtonCount: 5,
//deleteConfirm: "Do you really want to delete client?",
controller: {
loadData: function(filter) {
return $.ajax({url: "/js/jsgrid/estimates/index.php",data: filter });
},
/*insertItem: function(item) {
return $.ajax({
type: "POST",
url: "/estimates/",
data: item
});
},
updateItem: function(item) {
return $.ajax({
type: "PUT",
url: "/estimates/",
data: item
});
},
deleteItem: function(item) {
return $.ajax({
type: "DELETE",
url: "/estimates/",
data: item
});
}*/
},
fields: [
{ name: "estimateid", type: "number", width: 10, title: "EstId" },
{ name: "customerid", type: "number", width: 10, title: "CustId" },
{ name: "compid", type: "number", width: 10, title: "CompId"},
{ name: "first_name", type: "text", width: 50, title: "First Name" },
{ name: "last_name", type: "text", width: 50, title: "Last Name" },
{ name: "reference_num", type: "text", width: 12, title: "Ref.#" },
{ name: "estimate_date", type: "text", width: 12, title: "Est. Date" },
{ name: "expiry_date", type: "text", width: 12, title: "Exp. Date" },
{ name: "hours", type: "number", width: 10, title: "Hours" },
{ name: "sales_person", type: "text", width: 50, title: "Sales" },
{ name: "project_name", type: "text" , width: 50, title: "Project"},
{ type: "control" }
]
});
});

Lazy Load with Scrollable {Virtual:true} not working in Kendo UI Grid

I am facing an issue to implement lazy loading in kendo ui grid.
I added scrollable virtual property and backend server side code to handle it but issues is after adding scrollable property I am unable to see scroll bar in my Grid.
Even the selected rows (20 page size) disappears off the bottom of the grid into the hidden overflow area.
Here is my code.
var managecustomerGrid = $("#customerGrid").kendoGrid({
dataSource: {
schema: {
data: "results",
total : "totalRecords",
model: {
id: "SRNUMBER",
fields: {
SRNUMBER : {type: 'number'},
CUSTOMERNAME : {type: 'string'},
DATEPAID : {type: 'string'}
}
}
},
serverPaging: true,
serverSorting: true,
serverFiltering: true,
pageSize: 20,
batch: false,
transport: {
read: {
type: "POST",
url: "/customer/customer.cfc",
dataType: "json",
error: function (xhr, error) {
alert('Error In Getting Customer Information.');
}
},
parameterMap: function(options, type) {
return {
ntPageNumber: options.page,
ntRowLimit: options.pageSize,
vcSortOrder: JSON.stringify(options.sort),
vcFilterCondition: JSON.stringify(options.filter)
}
}
}
},
toolbar: kendo.template($("#template").html()),
height: 600,
scrollable: {
virtual: true
},
filterable: {
operators: {
string: {
contains: "Contains",
startswith: "Starts with",
endswith: "Ends with",
eq: "Is equal to",
doesnotcontain: "Doesn't contain"
}
}
},
sortable: true,
columns: [
{ field: "SRNUMBER", title: "SR No.", width: "80px", template: "<span id='#=SRNUMBER#'>#=SRNUMBER#</span>"},
{ field: "CUSTOMERNAME", title: "Customer Name", width: "110px"},
{ field: "DATEPAID", title: "Date", width: "110px"},
{ command: ["edit","detail","cancel"], title: " ", title: "Actions", width: "130px", filterable: false, sortable: false}
]
});
Please let me know if any one find any issues. I am unable to get it.
The kendo grid does not really support Lazy Loading out of the box. It may be easier to instead just make a blank scroll-able grid (without paging), and then to populate the data with ajax calls. You can use $.merge() to append data to the data array with little to no impact on performance.
$.ajax({
url: '/getNextData',
data: { filter: 'foo', lastLoaded: $("#Grid").data("kendoGrid").dataSource.at($("#Grid").data("kendoGrid").dataSource.total()-1).ID },
dataType: "json",
success: function (newData) {
$("#Grid").data("kendoGrid").dataSource.data($.merge($("#Grid").data("kendoGrid").dataSource.data(), newData))
},
error: function (e) { console.log(e); }
});
In this ajax example I load the next data based on the current last item in the grid and a filter. I just append the response to the currently loaded data.
I faced the same issue, my problem was the controller code. Here I am posting my controller hoping it would help someone someday
public JsonResult GetJson(int? projectid,int skip, int take, int pageSize, int page)
{
using (sqlCon)
{
var myData = sqlCon.Query<Device>("Select * from workbook.dbo.TargetList", new { projectid = projectid });
var data = myData .Skip(skip).Take(pageSize).ToList();
var total = myData .Count();
var json = new { data = myData };
var jsonResult = Json(new {data= data, total= total}, JsonRequestBehavior.AllowGet);
jsonResult.MaxJsonLength = int.MaxValue;
return jsonResult;
}
}

add record function in Kendo UI grid is called many times

I am using this html code for Keno UI grid
function loadPhoneGrid(salesRepsId){
$("#phone-grid").kendoGrid({
dataSource: {
transport: {
read: {
url: "operations/get_phones_sales_reps.php?salesRepsId="+salesRepsId,
type: "GET"
},
update: {
url: "operations/edit_phone_number.php?salesRepsId="+salesRepsId,
type: "POST"
},
destroy: {
url: "operations/delete_phone.php",
type: "POST"
},
create: {
url: "operations/add_phone.php?salesRepsId="+salesRepsId,
type: "POST",
},
},
schema: {
data:"data",
total: "data.length", //total amount of records
model: {
id: "PhoneId",
fields: {
PhoneType: { defaultValue: { PhoneTypeId: 1, PhoneTypeName: "Work"} },
PhoneNumber: { type: "string" },
IsMainPhone: {type: "boolean", editalbe:true},
}
}
},
pageSize: 5,
},
height: 250,
filterable: true,
sortable: true,
pageable: true,
reorderable: false,
groupable: false,
batch: true,
toolbar: ["create", "save", "cancel"],
editable: true,
columns: [
{
field:"PhoneType",
title:"Type",
editor: PhoneTypeDropDownEditor,
template: "#=PhoneType.PhoneTypeName#"
},
{
field: "PhoneNumber",
title:"Phone Number",
},
{
field: "IsMainPhone",
title:"Is Main",
width: 65,
template: function (e){
if(e.IsMainPhone== true){
return '<img align="center" src ="images/check-icon.png" />';
}else{
return '';
}
}
// hidden: true
},
{ command: "destroy", title: " ", width: 90 },
],
});
}
The code in the server side is (add_phone.php)
<?php
require_once("../lib/Phone.php");
$phone = array();
foreach($_POST as $name => $value){
$phone[$name] = $value;
}
Phone::AddPhoneNumber($_GET["salesRepsId"], $phone);
?>
For the first time, I added a new record. add_phone.php is calling once and everything is working fine. For the second time (with out refresh the page) when I try to add a new record, add_phone.php is called twice. One of them contains the first record which has been added to database before and the second is the new the data.
in the result I have 3 records ( 2 same data of first insert) and one new.
This an example to make it clear ( inspect the post request with firebug)
first click on save button (false, (111) 111-1111, 4,Fax) // after I enter this phone (111) 111-1111
second click on save button (false, (111) 111-1111, 4,Fax) in addition to (false, (222) 222-2222, 3,Work) // after I added this (222) 222-2222
Any help ??
May be your ajax request raise an error. You can see it by subscribing to the error event of your datasource.
In case of error, the data are not synchronized in your datasource. In your case, I think your dataitem stay in "dirty mode" so the datasource try to insert them for each synchronization...

Passing dynamic params to delete url method in JQGrid

I am using a JQGrid witha json service to list all the database users membership information, so the url of the grid points to my json service and method. Everything is working fine so far, I can add and edit the users and amend data and it saves fine. However the delete of a DB user is another story as the Membership.DeleteUser takes the username as its parameter. The JQGrid only seems to pass editable params back when in add or edit mode. But when you're trying to delete it doesn't seem to allow any params to be returned which I find very odd. I have only just started using JQGrids so I could just be being thick :-). Please can anyone tell me how to accomplish this? I have the username as a column in the JQGrid itself. I have tried various things to date:
url: 'misc/myservice.svc/AddEditDeleteGridRow?UserName=' + $('#MyGridTbl').getCell('selrow', 'UserName')
in the delete section of the navGrid. I have also tried setting the URL in the select row event too but I found it required a reload to insert it into the grid and when this happens the selected row is lost and so defeats the object. I just need to be able to access/get the username inside the json service in order to pass it to Membership.DeleteUser. I have been searching the internet and can't seem to find anything.
Here is the JQGrid I am using. There json service basically just has the GetData which returns JQGridJSONData (json object dataset) and AddEditDeleteGridRow methods in it, both are public. All the column data is being sent to the json service for the add and edit but nothing is being sent for the delete operation.
Just to clarify I need the UserName on the server side in the json service.
$('#MyGrid').jqGrid({
url: 'Misc/MyjsonService.svc/GetData',
editurl: 'Misc/MyjsonService.svc/AddEditDeleteGridRow',
datatype: 'json',
colNames: ['UserId', 'UserName', 'Email Address', 'Password Last Changed', 'Locked'],
colModel: [
{ name: 'UserId', index: 'UserId', hidden:true, editable: true, editrules:{edithidden: true}},
{ name: 'UserName', index: 'UserName', editable: true, width: 200, sortable: false, editrules: { required: true} },
{ name: 'Email Address', index: 'Email', editable: true, width: 500, sortable: false, editrules: { email: true, required: true} },
{ name: 'Password Last Changed', index: 'LastPasswordChangedDate', editable: false, width: 200, sortable: false, align: 'center' },
{ name: 'Locked', index: 'IsLockedOut', sortable: false, editable: true, edittype: "checkbox", formatter: 'checkbox', align: 'center' }
],
rowNum: 20,
hidegrid: false,
rowList: [20, 40, 60],
pager: $('#MyGridPager'),
sortname: 'UserName',
viewrecords: true,
multiselect: false,
sortorder: 'asc',
height: '400',
caption: 'Database Users',
shrinkToFit: false,
onPaging: function(pgButton) {
this.DBUserId = null;
},
onSelectRow: function(Id) {
if (Id && Id !== this.DBUserId) {
this.DBUserSelect(Id);
}
},
loadComplete: function() {
if (this.DBUserId)
this.DBUserSelect(this.DBUserId, true);
},
gridComplete: function() {
var grid = $('#MyGrid');
var body = $('#AvailableDBUsersArea');
if ((grid) && (body)) {
grid.setGridWidth(body.width() - 10);
//keep the grid at 100% width of it's parent container
body.bind('resize', function() {
var grid = $('#MyGrid');
var body = $('#AvailableDBUsersArea');
if ((grid) && (body)) {
grid.setGridWidth(body.width() - 2);
}
});
}
}
}).navGrid('#MyGridPager',
{ add: true, edit: true, del: true, refresh: false, search: false }, //general options
{
//Options for the Edit Dialog
editCaption: 'Edit User',
height: 250,
width: 520,
modal: true,
closeAfterEdit: true,
beforeShowForm: function(frm) { $('#UserName').attr('readonly', 'readonly'); },
beforeShowForm: function(frm) { $('#UserId').removeAttr('readonly'); },
beforeShowForm: function(frm) { $('#UserId').attr('readonly', 'readonly'); }
},
{
//Options for the Add Dialog
addCaption: 'Add User',
height: 250,
width: 520,
modal: true,
closeAfterAdd: true,
beforeShowForm: function(frm) { $('#UserName').removeAttr('readonly'); },
beforeShowForm: function(frm) { $('#UserId').removeAttr('readonly'); },
beforeShowForm: function(frm) { $('#UserId').attr('readonly', 'readonly'); }
},
{
//Delete options
width: 350,
caption: 'Delete User',
msg: 'Are you sure you want to delete this User?\nThis action is irreversable.'
},
{} //Search options
);
There are some ways to add additional parameters to the Delete URL. It would be helpful to have the definition of the jqGrid, especially colModel.
If you have a hidden column for example use can use
hidden: true, editable: true, editrules: { edithidden: false }, hidedlg: true
parameters. Then the hidden column would be not seen in the edit dialog, but the value of the column will be send.
Another way can you choose if you need modify URL befor sending Delete request. You can define parameter of navGrid (see prmDel paremeter on http://www.trirand.com/jqgridwiki/doku.php?id=wiki:navigator#how_to_use) which can be like following
{ onclickSubmit: function(rp_ge, postdata) {
rp_ge.url = 'misc/myservice.svc/AddEditDeleteGridRow?UserName=' +
$('#MyGridTbl').getCell (postdata, 'UserName');
}
}

Categories

Resources