I just started making a PHP/AJAX site and I was wondering where I should add the functionality to "only include the content".
Should I have if statements in my header and footer scripts that check for a "ContentOnly" get parameter? And then append that parameter to the query strings in my AJAX calls?
Or should I use a filter on the AJAX side to only grab the main content Div. Like in jquery:
$(this).load("/myPhpPage.php #mainContentDiv")
The first method would be faster right?
But the second method would keep the AJAX functionality on the presentation side, and out og my PHP.
Or is there a third method? I want to keep my PHP scripts intact, so that if oyu go to them directly, the header and footer are there. Thanks in advance!
Please don't use AJAX for the sake of using AJAX.
That said, most AJAX libraries pass a X-Requested-With HTTP header indicating that it's an AJAX request. You can use that header to decide whether to include your header/footer etc.
Depending on what paradigm you're using to handle page requests, I would generally recommend that you place such handling in the controller script. Handling view rendering logic that is specific to the type of request being made is entirely appropriate to place in the controller layer.
As ceejayoz suggested, you can use the X-Requested-With header (make certain that it is getting passed by your javascript library's ajax functions!) to verify in the controller script what the source of the request is and then render the view appropriately.
Adding to whats been said, your application shouldn't be aware of the rendered view. If you are making a call from javascript - javascript should know the context in which the call was made.
What this means is that the return handlers should know what they are handling during callback. The best method I've found for these types of transactions is to package objects in JSON that describe whats being called and who called it. Then when things are returned you can append some of these properties to the returned object. For instance if the same callback handler is used for everything you can simply pass the reference of the context back in this returned object.
Again though, don't use AJAX unless it serves a real purpose.
One place the X-Requested-With header came in very handy for me:
Very low-level authentication type method which would redirect to a login page... When requests are coming via AJAX, the redirect is a bad idea -- I want to return an XML payload with error response, so I throw an Exception for that instead. Yes, I could just have the authentication always throw, but then I have to implement handling that in every page and doing the redirecting there. Using X-Requested-With, I can get the best of both worlds.
X-Requested-With HTTP to indicate its a Ajax request is rather redundant. Ajax calls should never request HTML like the browser does!
In most cases AJAX calls shouldnt return html nor plain text. Make sure you specify the correct mime-type when doing the request to a page and have the page switch on the mime type used. This way when the browser request HTML it gets HTML when the AJAX call requests XML or JSON or if you must Plain text it will get the data in that format.
Edit: AHAH is a better term in this case indeed (technicality tho). I percieved content as data in the OP, which is why i was pushing mime-type so much.
I do however still think that getting ALL the content through ajax is a bad design, you lose more then you gain. It's better to go to a new page and expose some AJAX functionality within the content, IF needed.
And if that functionality AHAH's a small errorbox that doesn't need to be pushed in the history (which content does) for example so be it even my orthodox mind can live that :)
Even if you have a header which requires heavy calculation (i.e a treeview) there are other cache options that would benefit both the javascript-abled as -disabled as suppose only javascript-abled.
Thanks for the comments btw, i really did not want to come off as concieded but can see the note i struck was just that.
Related
my problem is - for now - not about specific code but more about basic understanding - I think.
I want to create a formular and use the data without refreshing the page, so that brings me to AJAX.
Now do I always have to create a seperate file that works with the data that AJAX sends? Can't I just "grab" the data and work with it on the same page?
I think I missunderstood some basic concepts.
I thought about something like this:
<form id="load_filters_form">
..
</form>
<?php
var_dump($_GET); // values from <form>
?>
<!-- AJAX, jQuery -->
<script>
$("#load_filters_form").submit(function(event){
event.preventDefault();
$.ajax({
type: 'get',
data: $(this).serialize()
success: function() {
$("#load_filters_form")[0].reset();
}
});
});
</script>
What you're proposing is certainly possible, it's exactly how AJAX works. You make an AJAX request from JavaScript code, sending any data the server-side code will need, and handle the response from the server in your JavaScript code.
The problem with what you're proposing is that you're making it unnecessarily complex for yourself. Consider what your code in the question would return to the JavaScript code in the AJAX response. It returns an entire HTML page, most of which is already on the client.
Why re-transmit all of that data that the client already has? Why have code on the client to parse out the data it's looking for from all of the unnecessary markup around that data?
Keep your operations simple. If you need a server-side operation which receives data, performs logic, and returns a result then create an operation which does exactly that. Call that operation in AJAX and use the resulting data.
Now maybe that response is structured JSON data, which your client-side code can read and update the UI accordingly. Or maybe that response is raw HTML (not an entire page but perhaps a single <div> or any kind of container which presents an updated version of a section of the page), which your client-side code can swap into the UI directly.
The AJAX interactions with the server should generally be light. If you're intentionally re-loading the entire page in an AJAX operation then, well, why use AJAX in the first place? The point is to send to the server only the data it needs, and receive back from the server only the data you need. For example, if all you need is to update a list of records displayed on the page then you don't need the whole page or even the HTML table of records, you just need the records. JSON is useful for exactly that, returning structured data and only structured data to the client. Then the client-side code can render that data into the structure of the page.
Now do I always have to create a separate file that works with the data that AJAX sends?
Yes and no. You may choose not to have a specific file which your ajax is pulling, but you do need some sort of Routing and Controller relationship as most frameworks build it.
You could in theory create a request to self (the same page) but that's bad logic. You are going to mix backend logic with frontend and will get messy - very quickly. You really need to separate all three elements,
PHP takes the data and process it
JavaScript takes the data and displays it
Your html should be code free; Just a pretty finalized product.
The best design pattern is to separate those files in their proper environment.
Can't I just "grab" the data and work with it on the same page?
Not really, at least not consistently. You also have to keep in mind it's a potential issue in attempting to serve two separate contents from the same route/file:
if ajax
// do something
else
// do the other thing
Ajax does not want fully rendered HTML files, it takes too long; it's best to serve JSON objects/arrays which will be rendered in your frontend via JavaScript; which was also used to make the request - in the user's browser without the latency caused by their network or your server.
There's no sure way of knowing which request is what since no data from the client is trustworthy, including HTTP headers; they are easy to fake and could potentially lead to security/unwanted results.
Thus, the best solutions is to have a foreign file which you would make the requests to, instead of doing it from itself.
I asked a similar question before, and the answer was simply:
if JavaScript can do it, then any client can do it.
But I still want to find out a way do restrict AJAX calls to JavaScript.
The reason is :
I'm building a web application, when a user clicks on an image, tagged like this:
<img src='src.jpg' data-id='42'/>
JavaScript calls a PHP page like this:
$.ajax("action.php?action=click&id=42");
then action.php inserts rows in database.
But I'm afraid that some users can automate entries that "clicks" all the id's and such, by calling necessary url's, since they are visible in the source code.
How can I prevent such a thing, and make sure it works only on click, and not by calling the url from a browser tab?
p.s.
I think a possible solution would be using encryption, like generate a key on user visit, and call the action page with that key, or hash/md5sum/whatever of it. But I think it can be done without transforming it into a security problem. Am I right ? Moreover, I'm not sure this method is a solution, since I don't know anything about this kind of security, or it's implementation.
I'm not sure there is a 100% secure answer. A combination of a server generated token that is inserted into a hidden form element and anti-automation techniques like limiting the number of requests over a certain time period is the best thing I can come up with.
[EDIT]
Actually a good solution would be to use CAPTCHAS
Your question isn't really "How can I tell AJAX from non-AJAX?" It's "How do I stop someone inflating a score by repeated clicks and ballot stuffing?"
In answer to the question you asked, the answer you quoted was essentially right. There is no reliable way to determine whether a request is being made by AJAX, a particular browser, a CURL session or a guy typing raw HTTP commands into a telnet session. We might see a browser or a script or an app, but all PHP sees is:
GET /resource.html HTTP/1.1
host:www.example.com
If there's some convenience reason for wanting to know whether a request was AJAX, some javascript libraries such as jQuery add an additional HTTP header to AJAX requests that you can look for, or you could manually add a header or include a field to your payload such as AJAX=1. Then you can check for those server side and take whatever action you think should be made for an AJAX request.
Of course there's nothing stopping me using CURL to make the same request with the right headers set to make the server think it's an AJAX request. You should therefore only use such tricks where whether or not the request was AJAX is of interest so you can format the response properly (send a HTML page if it's not AJAX, or JSON if it is). The security of your application can't rely on such tricks, and if the design of your application requires the ability to tell AJAX from non-AJAX for security or reliability reasons then you need to rethink the design of your application.
In answer to what you're actually trying to achieve, there are a couple of approaches. None are completely reliable, though. The first approach is to deposit a cookie on the user's machine on first click, and to ignore any subsequent requests from that user agent if the cookie is in any subsequent requests. It's a fairly simple, lightweight approach, but it's also easily defeated by simply deleting the cookie, or refusing to accept it in the first place.
Alternatively, when the user makes the AJAX request, you can record some information about the requesting user agent along with the fact that a click was submitted. You can, for example store a hash (stored with something stronger than MD5!) of the client's IP and user agent string, along with a timestamp for the click. If you see a lot of the same hash, along with closely grouped timestamps, then there's possibly abuse being attempted. Again, this trick isn't 100% reliable because user agents can see any string they want as their user agent string.
Use post method instead of get.Read the documentation here http://api.jquery.com/jQuery.post/ to learn how to use post method in jquery
You could, for example, implement a check if the request is really done with AJAX, and not by just calling the URL.
if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
// Yay, it is ajax!
} else {
// no AJAX, man..
}
This solution may need more reflexion but might do the trick
You could use tokens as stated in Slicedpan's answer. When serving your page, you would generate uuids for each images and store them in session / database.
Then serve your html as
<img src='src.jpg' data-id='42' data-uuid='uuidgenerated'/>
Your ajax request would become
$.ajax("action.php?action=click&uuid=uuidgenerated");
Then on php side, check for the uuid in your memory/database, and allow or not the transaction. (You can also check for custom headers sent on ajax as stated in other responses)
You would also need to purge uuids, on token lifetime, on window unload, on session expired...
This method won't allow you to know if the request comes from an xhr but you'll be able to limit their number.
I have a .php file from another server which processes data. This data is tabulated. So whenever I call this page using $.post with the right parameters, its response is nothing. I checked my code and maybe the header is the one responsible for it. What I want actually is to return my tabulated data so that I can populate it to another page. My header is like this, header("Content-type: application/json");. What am I missing?
$.post('http://333.333.33.33/reporting/table.php?loc_id='+locid+'&loc_type='+loctype+'',{loc_id:locid, loc_type: loctype},function(data){
$('table#default_table').hide();
$('div#generated_table').html(data);
});
that is how I call my $.post.
You my friend have become yet another victim of the Same Origin Policy - luckily, this can be "worked around" by using a method called JSONP. This does, however, require a GET rather than a POST request. I myself had to use this, and I had no idea about how it worked, so I asked a question and got a wonderful answer!
You need to communicate between 2 different domains right?
You need to use JSONP here instead JSON.
Check Detail
I am working on a live weather data page. Our weather module outputs the data in CSV and stores it on my webserver. I then use a PHP script to translate the CSV into an array and then i encode it in JSON and output it so that my jQuery Ajax script can call it every so often to get the latest data and update the page. This is working great so far.
My question is, how can i prevent the URL used to retrieve the JSON (the URL of the aforementioned PHP script) to be opened and viewed in a browser? I tried adjusting the permissions, but to no success.
Thanks in advance to any who are willing to help.
There's no real way of doing that, since the Ajax call also comes from the browser. There's no real difference between a proper browser call and an Ajax call. A GET call is a GET call.
EDIT
As per #Adeneo's suggestion, implementing a pseudo-security, through some kind of key, would be a good way of making it harder for people to view the page, even though there's no way of literally blocking the call.
Also, adding a header to your Ajax call and verifying the presence of that header in your backend script makes it a bit harder to spoof.
Another idea would be that, if that service would be called only once per page view, you could setup a key in your javascript, provided by your server, to append to your ajax call. When the server gets called, the key provided becomes invalid after use, preventing someone from calling the service with the same key twice.
There is no way of (reliably) identifying a browser as anything that is not some form of "Authentication-Token" can be faked. The server relies on the client to be honest.
You can detect if a request is an ajax request tho. Here is a link to one way of doing it:
http://davidwalsh.name/detect-ajax
This is how he does it:
/* AJAX check */
if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
/* special ajax here */
die($content);
}
You will want to reverse the statements in the if since it die()s when the request IS ajax.
There are other ways of detecting ajax, none of which are 100% secure, including you setting a GET variable that helps you identify an ajax call (but that get variable can also be sent via the browser via the address line so well... you get the picture)
Short answer: you cannot.
Long answer: you could implement a simple Browser Sniffing. Or search for far more advanced methods.
$browser = get_browser(null, true);
if ($browser[parent] == "whatever-identifies-clients-that-have-access") {
//Code to output jSon here.
}
else {
header('HTTP/1.1 403 Forbidden');
}
But note that this is not security. At the very most, it throws up a barrier; but preventing is impossible.
Edit This assumes the client is not a browser, I wrongly assumed a (mobile) client of some sorts was accessing the JSON. When it is a browser, you cannot deny access. At all. AJAX comes from that browser too.
I have some variables set in Javascript. Further down the script I want to use these values in PHP. I realise I need to POST/GET them with jQuery, but I don't understand either function fully, even after looking at the manuals.
Could somebody break it down and explain the parameters?
Would I be better off using GET or POST in the instance?
Can the URL specified be the same as the current page e.g. index.php?
Thanks very much for your help.
You can not do this unless PHP is writing the javascript. PHP is on the server side and will be parsed before Javascript is ever seen by the client. Any variables set by JS will NOT be seen by PHP on the same request.
It's really just a question of style, really.
GET places all key/value-pairs in the URL field, whereas POST puts it in the HTTP body. Since URLs are limited in length, POST is preferred for longer, larger sets of data or data needing to benefit from TLS/SSL encryption.
So let's say we have a key: articleID. You want to pass 1 to articleID, so that the backend can contact the database and retrieve the article in question.
If you make a GET request, you'd invoke the following URL:
index.php?articleID=1
If you use POST, you'll put the data in the request body itself, so you wouldn't be able to tell what value you sent to the server without opening the packet in question and examining the request.
You'll find more information on how to perform these requests back at jQuery's reference site. More information about GET and POST.
You are the architect of the application, so you would know best what method to use. As for contacting the view itself, it's certainly possible albeit questionable from an architectural point of view.