jQuery check file - php

I make ajax calls to the file /ajax.php
It gives me some data.
How do I check inside ajax.php, was this file directly opened in browser or by a true ajax call?

Quick and dirty answer is like, you can't make it sure 100%. An "AJAX" request still is a normal HTTP request. Probably the best way to somewhat verify that is to set a custom HTTP header for which you have to check on the server side.
For instance, it's a common practice to add a X-Requested-With header to the HTTP request if it was an ajax request. jQuery for instance puts that header in all its request under the hood.

I think the usual way PHP developers do this is to pass a flag to the server during the ajax request.
The usual flag I've seen has been: ajax: true
$.ajax({
url : "/ajax.php",
type: "POST", // If you want to send the data as a POST rather than GET
data: ({ajax: true})
});

the best way to make sure this was a true ajax request would be to use tools like firebug, fiddler or the network tab in the google chrome developer tools. you can then observer the traffic between your browser and the server, contents of the traffic etc..

Related

How have safe HTTP Request Method

when use GET Method for receive JSON data , we can acsses the result directly from web browser , for example i send a mydata value from ajax to a main.php file and it process and get answer show a result some thing like below :
<?php
if (isset($_GET["mydata"])) {
if ($_GET["mydata"]=="hello"){
echo "hello world";
}
}
?>
but when a user call it in browser directly like http:mysite.com/mydata.php?mydata=hello recive answer . i want dont allow users to get answer of http request directly , and just can show it from ajax result of main page is it possible ?
You're asking how to prevent an ajax-only request from being accessed directly by copy-pasting the URL into the web browser; that is, only allowing the URL to be accessible via ajax on the main web page.
Well, there are a few things you can try:
Check the Referrer for the URL of the main page with $_SERVER['HTTP_REFERER']
Set a header in Javascript using xhr.setRequestHeader() and then ensure it's value by checking for $_SERVER['HTTP_X_....'] in PHP
Like Jay Bhatt recommended, check for the X_REQUESTED_WITH header, but be aware this might not always be set (see: X-Requested-With header not set in jquery ajaxForm plugin)
However, in any of these situations you should be aware that anyone who knows what they are doing can easily set any HTTP header, variable, or even modify the referrer which is sent to the server. As such, there is no 100% guarantee that your resouce can be accessed only via AJAX on the main web page. There is no control built in the internet to verify where a request is coming from, so anyone can easily spoof or fake it.

Send Variables POST and GET

How can I request a URL with my own variables without using it through a HTML form?
Thanks!
EDIT:
When a specific page loads I want to send a request to a url with a couple of my own variables.
Ex: I come to www.example.com/done
the page sends a request to www.example2.com?abc=123&def=456
Your question is too broad, but there is an answer...
By issuing HTTP request in a different way, for example:
by calling it using AJAX from some website (eg. jQuery.post()),
by issuing a request using some kind of tool, like browser extension (eg. Postman REST Client or Simple REST Client for Google Chrome),
by using some library to do such call in an automated way (eg. Requests library for Python),
In general, GET parameters are passed in the URL, while POST parameters are passed in the body, so to pass both, you need to do both, by issuing POST request and:
appending GET parameters to the URL, in URL-encoded way (like "...?par1=1&par2=2"),
passing POST parameters in the body of the request, also URL-encoded
POST variables are either sent through a form (hence, POSTing them), or sent using AJAX.
GETvariables, however, are simply passed through the URL. For instance, if you wanted to send foo=bar to example2.php, you could use
Go to example2.php
And then in example2.php, you could say
$foo = $_GET['foo'];
Simple. :)
Use AJAX in javascript. For a beginner I'd recommend using the jQuery library
$.get("url", {key: "value"}, function(resp) {})
or
$.post("url", {key: "value"}, function(resp) {})
Should suffice

Differentiate between a browser GUI request and an AJAX request

What is the best way within my PHP script to differentiate between a normal browser GUI request and an AJAX request?
Not as such.
You can write your JavaScript in such as way to to leave some sort of identifier in the request headers that you could use though. See the XHR setRequestHeader method.
A nice use of HTTP would be to modify the Accept header and then do normal content negotiation. Then (for example), instead of caring if it is Ajax or not, you just care if an HTML response is preferred over a JSON response.
Another convention is to use the non-standard X-Requested-With header with a value of XMLHttpRequest. A number of JavaScript libraries will add this by default to any request using XHR.
Either of these techniques will only work with XMLHttpRequest or plugin based Ajax though. You can't set arbitrary HTTP headers for JSON-P or iframe based Ajax.
As far as the server is concerned, there is no particular difference between a normal request and one initiated by Javascript.
If you want to identify a particular brand of request, a reasonable approach is to pass a custom header.
$.ajax(uri, {
beforeSend: function(xhr) {
xhr.setRequestHeader('X-YourApp-AJAX', '1');
});
Providing you're using Apache, checking for the header you just set in your PHP is easy enough.
$headers = getallheaders();
if(isset($headers['X-YourApp-AJAX'])) {
// AJAX request
} else {
// ...
}
Edit
Looks like jQuery, amongst others, already passes an X-Requested-With header in AJAX requests – use that in preference.

Does $_SERVER['HTTP_X_REQUESTED_WITH'] exist in PHP or not?

All over the Internet, included even here at Stack Overflow, people state that a good way to check if a request is AJAX or not is to do the following:
if (strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest' ) {...}
However, I don't see $_SERVER['HTTP_X_REQUESTED_WITH'] in the official PHP documentation
And when I try to do the following:
echo $_SERVER['HTTP_X_REQUESTED_WITH'];
Nothing is outputted.
Am I doing something wrong? Because I'd really like to be able to use $_SERVER['HTTP_X_REQUESTED_WITH'] if it's available.
The variables in $_SERVER are not really part of PHP, which is why you won't find them in the PHP documentation. They are prepared by the Web server which passes them on to the scripting language.
As far as I know, the X-Requested-With is sent by the Ajax functions of most major Frameworks but not all (Dojo, for example, added it only two years ago: #5801). As such, and taking into considerations #bobince' comments, it's safe to say it's not generally a 100% reliable method to determine whether a request is an AJAX request or not.
The only 100% secure way is to send a pre-defined flag (e.g. a GET variable) along with the request and for the receiving page to check for the presence of that flag.
don't forget that you can easily spoof any header with cURL like so
curl_setopt($ch,CURLOPT_HTTPHEADER,array("X-Requested-With : XMLHttpRequest"));
$_SERVER keys that start with HTTP_ are generated from HTTP request headers. In this case, the X-Requested-With header.
This header is a standardization-in-progress from all of the AJAX libraries out there.
It won't be documented in the php documentation per-se, but rather in the different AJAX libraries that set this header. Common libraries do sent this header: jQuery, Mojo, Prototype, ...
Usually these library will set the header using
xhrobj.setRequestHeader("X-Requested-With", "XMLHttpRequest");
Here's a quick function with example usage:
function isXmlHttpRequest()
{
$header = isset($_SERVER['HTTP_X_REQUESTED_WITH']) ? $_SERVER['HTTP_X_REQUESTED_WITH'] : null;
return ($header === 'XMLHttpRequest');
}
// example - checking our active call
if(!isXmlHttpRequest())
{
echo 'Not an ajax request';
}
else
{
echo 'is an ajax request';
}
echo $_SERVER['HTTP_X_REQUESTED_WITH'];
What'd you expect from such a code? Assume you're running it directly from the browser, not using AJAX request. So, how come this header could be set?
Well the Answer to the Ultimate Question of Life, the Universe, and Everything - an HTTP sniffer! Get yourself one and forget of printing $_SERVER variable.
Firebug has one, or you may want to use Fiddler HTTP proxy or LiveHTTPHeaders Mozilla plugin. I'm bored to make links but it easily googled.
So, with HTTP sniffer you can be sure of any HTTP header ever.
Note that you can't prevent any "direct access" by using XHR, as every HTTP request to your server is already "direct".
You have to set it specifically in your ajax request object (that is if you are not using a framework like jQuery), but core Javascript; like so:
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
Where xhr is your request object.
Then, PHP will now receive and set it in the global variable $_SERVER like so:
$_SERVER['HTTP_X_REQUESTED_WITH']
Otherwise $_SERVER['HTTP_X_REQUESTED_WITH'] will always be null.
Note: In your javascript, Please make sure you set headers after the request is open. I mean after xhr.open() method.
You can also blame some browser bugs - see this question and its solution for Firefox
Firefox does not preserve custom headers during Ajax request redirect: an ASP.NET MVC solution
IE also having caching issue which is more serious then detection of request method.
You anyway needs to add cache busters to avoid caching, so why not use another flag to specify the ajax call - or more better you can use different URL like http://ajax.mysite.com/endpoint/sevice?params
I agree Pekka. There is no reliable native method between front side and back side that can auto-detect if a client is really calling an endpoint using AJAX.
For my own use, I have few main ways to check if a client is requesting one of my endpoint:
I can use HTTP_X_REQUESTED_WITH when I'm not in cross domain context.
instead of checking "X-requested-with", I'm checking $_SERVER['HTTP_ORIGIN'] (that is sent from AJAX request) intending to handle cross domain permissions. Most of time, the main reason why I'm checking if a request is an AJAX request, is especially because of cross domain permissions, using this PHP code: header('Access-Control-Allow-Origin: '.$_SERVER['HTTP_ORIGIN']); // If this "HTTP_ORIGIN" is in my white list
my APIs expect from the client to explicit, in few cases, the datatype (JSON, HTML etc.) into a GET or a POST var. For example, I check if $_REQUEST['ajax'] is not empty or equal to an expected value.
The best solution to make sure if an HTTP request is truly sent via AJAX is using SESSION checking , you send session_id in a get parameter and you check this session if it's allowed or not !
$headers = apache_request_headers();
$is_ajax = (isset($headers['X-Requested-With']) && $headers['X-Requested-With'] == 'XMLHttpRequest');

Form that makes browser redirect when accessed by either a regular form submit or an Ajax request - is this possible?

I have a web page with a form. When the user submits the form, I want the server to make the browser redirect to a different page from the form action. Right now, I am doing this by using PHP's header function to send a 302 status code. It works fine.
I am trying to make the page on the server redirect the browser in the same way, regardless of whether it was submitted normally (without Javascript) or via Ajax. I tried to do this by setting the window location to whatever URL is in the Location header. I am using jQuery, and doing a call like this:
$.ajax({
url: this.action,
type: "POST",
data: getFormData(this),
complete: function(request) {
window.location.assign(request.getResponseHeader("Location"));
}
});
However, that didn't work. After thinking about it, I realized that this is not very surprising. In an Ajax request, the browser is supposed to transparently handle redirect responses such as 302 codes before changing the readyState. When the complete function runs, it is looking for the Location header in the final destination and not finding it.
As an experiment, I then tried sending a 200 status code with a Location header. I tried the Ajax request and it worked fine. However, when I did the non-Ajax submit, it didn't work. The browser went to the form action page and stayed there, like it was ignoring the Location header.
Is there any way to make the same page redirect in both cases, without the server having to know or care whether the request is an Ajax request?
In case this matters, I tried the form in various browsers (IE8, IE7, IE6, Firefox 3.5, Chrome) with similar results each time. Also, I am doing a post request to avoid bumping into IE's 2083-character URL length limit.
HTTP 302 response are consumed silently by XmlHttpRequest implementations (e.g. jQuery's ajax function). It's a feature.
The way I've solved this in the past is to detect for XmlHttpRequests and issue a "Content-Location" header (rather than a "Location" header). The most cross-library way of doing this is to check for the "X-Requested-With" http header in your server-side code (jQuery, Prototype, Mootools among others set this):
if (#$_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') {
header('Content-Location: ' . $redirect_url);
} else {
header('Location: ' . $redirect_url);
}
You still need to special-case your client-side code:
$.ajax({
// ...
complete: function(xhr) {
var redirect_url = xhr.getResponseHeader("Content-Location");
if (redirect_url) {
window.location = redirect_url;
}
}
})
If the user is getting redirected regardless, why the Ajax? The whole point of Ajax like this is to make changes to the page without a page refresh, so the technique you're using seems a little like building a printer that outputs into a shredder hopper.
I'd like to know more about your use-case for this. From what I understand your trying to get your application to load a page based on the 'Location' header of an Ajax call within it? I'd ask why?
An HTTP header doesn't seem to be the right place to get that information from. Isn't your application essentially making a query that says "Where shall I redirect to?". There's no reason the Ajax response actually has to respond with a 302 and a 'Location' header. Why not just have it respond with JSON or XML which contains the new URL?
Edit: Just re-read your penultimate paragraph. I'm not sure there's a good way of achieving what you want. The concept sounds broken to me. :)
Pass additional parameter to your ajax request for easy identify type of request. When ajax - do not redirect - just send target url, then redirect client side in ajax callback via location.href
like this:
$.post('/controller/action', {formdata}, function (redirect_to) {
location.href = redirect_to;
});
Will "complete" work:
$.ajax({
type: frm.attr('method'),
url: frm.attr('action'),
data: frm.serialize(),
complete: complete(xhr, status) {
window.location.assign(xhr.getResponseHeader("Location"));
}
});
Did you try using the error function instead of complete?
$.ajax({
url: this.action,
type: "POST",
data: getFormData(this),
error: function(request) {
if(request.status == 302)
window.location.assign(request.getResponseHeader("Location"));
}
});
jQuery sends any 3xx response to the error function. Maybe the 'Location' header will still be available at this stage.
Why not have your "ajax action" simply fill in the needed form fields and submit the form instead? This way you'll get exactly the same behavior as when submitting by hand.
Here is another option although you will need to do some cross browser tests:
complete: function(request) {
if(request.status == 200) {
var doc = document.open(request.getResponseHeader('Content-Type'));
doc.write(request.responseText);
doc.close();
}
}
Major drawbacks: URL in address bar doesn't change; could mess with back button/history
Although I think #crescentfresh's idea is the way to go

Categories