How would you go about using tokens with the following?
$('#DIV').load('child.php?id='+id);
So that you couldn't access child.php straight from the browser and type child.php?id=1
If this is not possible with tokens would there be any other way?
Thought about XMLHttpRequest as follows:
var mygetrequest=new ajaxRequest();
mygetrequest.onreadystatechange = function(){
if (mygetrequest.readyState==4){
if (mygetrequest.status==200 || window.location.href.indexOf("http")==-1){
document.getElementById("DIV").innerHTML = mygetrequest.responseText;
} else{
alert("An error has occured making the request");
}
}
}
mygetrequest.open("GET", "child.php?id="+id, true);
mygetrequest.send(null);
Many thanks.
What you need is to check if the request is an ajax request (from load()) or not, this can be done by the following:
child.php:
if(isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
// it's an ajax request validate id and continue!
} else {
// this is not an ajax request, get out of here!
}
You could use jQuery post to send the parameters "behind the scene" and then check if the request was sent from a certain location or IP within the actual php file. If the location or IP does not have the authority to access it, simply output an error using e.g. the die() method before anything else has been output.
Related
I need only PHP answers.
Setup : Apache Server and PHP version 7.4.
I'm working on a CAPTCHA plugin for WordPress. On that purpose, I thought I'd validate the CAPTCHA field before validating any other request.
This means I want to perform the CAPTCHA POST request before any other $_REQUEST is complete.
These other requests can be multiples, and I won't be able to handle their scripts.
I thought I'd detect if a POST or GET request has been made, then maybe call sleep() and perform my POST meanwhile.
The problem is : sleep() pauses the whole script whereas I only want the other POST and GET requests to be paused...
if ($_SERVER['REQUEST_METHOD'] === 'POST' OR $_SERVER[‘REQUEST_METHOD’] === 'GET' AND $_POST["myRequest"]) {
// Pause every POST and GET requests apart from $_POST["myRequest"] until $_POST["myRequest"] is performed
} else {
continue;
}
You could use session and keep track of the request and save the request if $_POST['myRequest'] is not present, than load the previous request from session or a file. Like this:
<?php
session_start();
if ($_SERVER['REQUEST_METHOD'] === 'POST' OR $_SERVER[‘REQUEST_METHOD’] === 'GET') {
// POST myRequest has been done before
if(isset($_SESSION['.my-request.lock'])) {
// If present remove it
unset($_SESSION['.my-request.lock']);
if(isset($_SESSION['my-data.json'])) {
$my_prev_request = json_decode( $_SESSION['my-data.json'] );
unset($_SESSION['my-data.json']);
}
// Process other requests
} else {
if(isset($_POST['myRequest'])) {
$_SESSION['.my-request.lock'] = true;
// Do your own thing
} else {
// No myRequest and no file, save request data to load it after POST myRequest
$_SESSION['my-data.json'] = json_encode( $_REQUEST );
}
}
} else {
// Display Error ?
continue;
}
I'm working with Slim Framework and I would like to redirect the user to the login page if the user has lost his session but I'm always getting a SyntaxError : Unexpected token < at position 0.
My session validation code in php is this:
private function _validaSessao() {
$user = $this->userData['IdUser'];
if(null === $user || trim($user) == '') {
header("Location: http://192.168.0.9/", true, 301);
die();
}
}
I've tried that and all the following:
header('refresh:5;url=http://192.168.0.9/');
echo '<script>window.location.href = "http://192.168.0.9/";</script>';
return('<script>window.location.href = "http://192.168.0.9/";</script>');
echo json_encode('<meta HTTP-EQUIV="REFRESH" content="0; url=http://192.168.0.9/">');
I've tried them all and I'm always getting
200 ---- SyntaxError: Unexpected token < in JSON at position 0
The only piece of code that worked for me was:
echo json_encode(array(
'SemSessao' => true
));
But the above code makes me checking on every single call on JavaScript and I would like a solution that PHP will redirect me. This way I wouldn't need to keep checking on every single JS call (which are a lot) and each time a php object was instanciated it would check for session and redirect the user without the use of JS.
Update 1 - Include JS code (lovely downvotes everywhere :D)
getDadosPlaneamento: function() {
var req = {Rota: '/planeamento/getDados/AUTO'};
var dfd = $.Deferred();
$.when(App.gajax(req)).done(function(d) {
On.Planeamentos = d.Planeamentos;
dfd.resolve();
});
return dfd.promise();
},
The above code is what refers to my php route and then:
$onapp->get('/planeamento/getDados/:tipo/', function($tipo) {
if ($tipo == 'AUTO') {
$P = new MongoApi\Planeamento();
$ret = array(
$P->getAllMongo();
);
}
echo json_encode($ret);
});
And when I do $P = new MongoApi\Planeamento(); I check if the user has a valid session on the constructor using _validaSessao();
The server cannot redirect a client from an AJAX call. The AJAX call is a background HTTP request. Whether that HTTP requests gets redirected or not is irrelevant to the browser. The browser will return the request response to the AJAX client, and if that response is "your request has been redirected" then that's that. Again, a redirect doesn't redirect "the browser", it redirects the HTTP request. Or more precisely speaking, it tells the HTTP client that it should retry its request somewhere else; nothing more.
If your AJAX requests can fail due to a session timeout and whenever that happens you want to present the user with a login page, you will have to do that client side. In order to not repeat that same code every time, you make a function/object/service out of that. E.g. something along the lines of:
function makeAJAXRequest(url, data) {
return fetch(url)
.then(response => {
if (response.status == 403) {
window.location = '/login';
throw new Error('Forbidden');
} else {
return response;
}
});
}
Here the server is expected to respond with a 403 Forbidden status code for unauthorised requests. If you make all your AJAX requests through this function, it will automatically handle that case by redirecting to the login page.
Remeber that header() must be called before any output is generated. you can use ob_start() and op_end_flush() to avoid output previous to your header.
ob_start ();
header ("Location: http://192.168.0.9/", true, 301);
ob_end_flush ();
In my ajax.php has:
if(urlvar(2) == 'uploadphoto'){
do... echo '<img... />';
}
But this functions is only called by a jquery, returning on a specific div.
But if I visit the URL: [http://localhost/projectname/ajax/uploadphoto], this page returns the result of function with some erros (because the parameters are sent by jquery)
How I can prevent returns, if the file is accessed without jquery?
*SOLVED:
Use this function in functions that cannot be accessed without jquery method.
function isHttpRequest()
{
if( #$_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') {
return true; //acessed by jquery
}
exit; // or return false -> from access the file without method
}
When you access the file via jQuery, you write something like:
method: "get" or method:"post" (The default, if not specified, is GET, I think)
So, at the beginning of your ajax.php - put:
if(!$_GET){
//[...the ajax.php code, here ...]
}
I personally create a hash in every form
and i check if that hash is correct , this prevents people from submitting forms from other servers too and it may help in your situation
http://code.tutsplus.com/tutorials/secure-your-forms-with-form-keys--net-4753
if the hash is wrong then it's abviously not coming from the form that it should come from
Modify your ajax.php to check if the request is an ajax call.
if(empty($_SERVER['HTTP_X_REQUESTED_WITH'])
|| strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) !== 'xmlhttprequest') {
// not an ajax request
} else {
if(urlvar(2) == 'uploadphoto'){
do... echo '<img... />';
}
}
Or just check at the beginning of ajax.php
im receiving a json file from an external call. If the json comes with a null value (possible if the user session is expired) then the user should be redirected to the logout.php page. In my current call, instead of redirecting, the logout.php data is being received as a json response.
So, how do I redirect the user when the json data is null?
$.getJSON(sSource, aoData, function (json) {
if(json !== null) {
fnCallback(json);
} else {
window.location.href = "logout.php";
}
});
Thanks to #Ron's observation i noticed that, although sSource was calling the right file (datatables.php), its header isn't detecting the request method, hence returning the wrong data:
if(($_SESSION['login_expire'] + $session['expiration_time']) < time()) {
if($_SERVER['REQUEST_METHOD'] == 'POST') {
# forms
} else {
if(strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
# datatable
header('Content-type: application/json');
echo json_encode(null);
} else {
# get
header('Location: '.URL_CMS.'logout.php?expired=true');
}
}
die();
} else {
# update expiration time
$_SESSION['login_expire'] = time();
}
That last bit controls idle times. It should also consider ajax calls, in which case it should return a json_encode(null) string instead of redirecting via php:
if(strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest')
What you want is for your PHP to return some JSON that includes a response status and then use that response to send them to the error page if it's a bad status. For example, have your PHP return {"status":"failed", "message":"Expired"} instead of setting the Location header like it is currently.
Then in your Javascript:
if(json.status != "failed") {
fnCallback(json);
} else {
window.location.href = "logout.php";
}
I am doing a simple ajax request to another domain like this:
<script type="text/javascript">
$(function() {
$('.clik').click(function() {
$.ajax({
type: "POST",
url: "http://sub.mydomain.com/test.php",
crossDomain: true,
dataType:"jsonp",
success: function(data) {
$('p.txt').html(data['no']);
}
});
});
});
</script>
</head>
<body>
<p class="clik">Halleluja</p>
<p class="txt"></p>
this is the test.php page on sub.mydomain.com
<?
header('Access-Control-Allow-Origin: http://mydomain.com');
// Begin Session
require_once('cl.session.php');
$session = new Session();
$session->start_session('test', false);
// Access Database
require_once('cl.database.php');
$login_db = new Database('user', 'pass', 'accounts', 'test');
$login_pdo = $login_db->PDO;
include "fn.check_login.php";
if(checkLogin($login_pdo) == true) {
// We start out by checking if the request has been made using AJAX
if (is_ajax()) {
echo "this is working";
} else {
echo "this is not working!";
}
} else {
echo 'You are not authorized to access this page, please login. <br/>';
}
// Function to check if the request is an AJAX request
function is_ajax() {
// BOOLEAN return if AJAX
return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest';
}
?>
It returns a semantic issue.
Also if I simply echo some basic text:
<?
echo "Hello World!";
?>
it still returns a semantic issue.
could somebody tell me what went wrong?
Well, for a start, JSONP requests can't be POST (only GET). But I tend to assume jQuery is ignoring the invalid type. JSONP is intrinsically a GET.
Your response to it is invalid. You've told jQuery you're expecting the server to provide a JSONP response. but your responses aren't JSONP.
A JSONP response would look something like this:
callback({
"property": "value",
"anotherProperty": 42
})
...where the name of the callback (callback in the above) is taken from the query string of the request. So for instance, if the request were http://sub.mydomain.com/test.php?callback=foo, the response would use foo for the name of the callback:
foo({
"property": "value",
"anotherProperty": 42
})
jQuery will add the callback= query string parameter to the request for you automatically, and generate the corresponding function for you, which in turn calls the ajax success handler with the data passed into it.
I think you may need to use the jquery postMessage plugin (or similar if there is one). Long time since I tried it but check if you load the script from the server you wish to call (think I tried that and failed in the past but hey - its worth a bash - report back if it does).