Quick question, I have tried figuring this out myself, but the use of Session Variables can be confusing when trying to figure out why or how a page is reloading and doing/not doing what it is supposed to do.
Does a page reload (with JavaScript, f5, ctrl+f5, browser reload button, etc) ever, under any (non-scripted) circumstance cause a form repost?
(This pertains to using IfPost branches within C# code like the example code below):
if(IsPost)
{
//stuff that only executes if the previous request was a post.
}
I just kind of need to know what to expect here so I can properly diagnose my session state problems.
Thanks for any help!
(Also, sorry if I am oversimplifying this question. I realize that it 'may' be more complicated than a simple answer can provide).
******UPDATE**********
Also, I looked for copies of this question here, on StackOverflow, but I didn't see anything, so if this is a duplicate question, I apologize.
Both of the answers here are good answers. I accepted the answer that also offered a solution to my question, and while PRG is not the 'only' way to do it, it seems like it may be the best. It also seems a growing way to handle client-side user-friendliness, and imho, seems like it would be a great habit to get into.
Thanks for showing me that!
Yes. If the page was loaded using POST data this will occur. To prevent this you need to implement the POST/REDIRECT/GET pattern.
Post/Redirect/Get (PRG) is a web development design pattern that prevents some duplicate form submissions, creating a more intuitive interface for user agents (users). PRG supports bookmarks and the refresh button in a predictable way that does not create duplicate form submissions.
Yes. If someone refreshes the browser manually, it will ask them if they want to send the form data again. This will cause that code to get executed.
A way to handle this is using tokens.
Send a random string along with the post data
Store this random string somewhere
When you check the post data make sure that the stored string is the same as the string in the post request.
If true, handle the request.
Generate a new token
If someone were to refresh and resend the post data, your token in the post request will be different from the one you stored separately since you generated a new token at step 5
Related
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.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Back button re-submit form data ($_POST)
I know that for security reasons it is better to use POST method than GET.
Anyway, if you have several web pages and you wanna navigate between them, if you USE POST method your browser will re-submit data of the prevoious form if you press te BACK or FORWARD button.
There is a way to use POST method BUT let the user navigate between previous or next page without resubmit data?
I do not know if
There is no security difference between POST and GET. If you do not want to have the resubmitting problem. You should follow the Redirect-After-Post pattern.
Edit:
For all the guys seeing a difference in terms of security.
You can sniff either of those via Man in the middle in plain text(while not having https)
You can resend both requests
You can invent security tokens for both methods
The only difference is that POST does not expose information by the URL identifier. But an attacker will always check also sourcecode.
Having POST to insert data in databases etc. is not because of Security. It is because of the widely used REST paradigma. But the REST paradigma is not a MUST while developing a web application. It is like any standard you may follow its guidelines or you leave it alone.
There is btw also a nice post on the exact same topic with the same findings: Is either GET or POST more secure than the other?
Using the POST method isn't necessarily more secure than GET.
For the sake of browsing between different pages something like ?page=home is perfectly ok, as long as you check the input before processing it.
I know no method to stop browsers asking to resend the data, because there are good reasons to ask the user if he wants to send them again.
POST is not better than GET. POST is just more suitable if you want to do an operation that's gonna make a change in the DB (write). GET is... getting something from the DB (read). So to navigate between pages (and pagination), there's nothing wrong in using GET.
There is nothing wrong with using $_GET in your script, just dont insert data based on a GET request and if you show data used from a GET, make sure you htmlspecialchars(); it before outputting it to the user.
As the title says, is there another way to pass a variable from "current" page over to "next" (new HTTP request) page without using sessions/cookies/$_GET?
Well, I guess $_POST could be an option too, but the thing here is, that I want to pass this variable from already executed $_POST back to off-the-post environment page, but inbetween I'm having a redirect, to disallow reposting the same form.
In other words, basicly, I'm trying to "make" a seamless PRG, but sessions/cookies/$_GET is not an option.
And yes, I'm working with classes (hence the oop tag). Therefore maybe some kind of magic functions, or output control?
This has to work within PHP environment, no JavaScript or other non server side language.
I also have a bad feeling that it's impossible, but hopefully I'm wrong, and there is a solution.
Thanks in advance!
update no. 1
Basicly, I want to create a PRG with response.
Inside this $_POST I'm adding data to database. I want this response to hold information whether this database query has been successful or not. Kind of make this $_POST process almost invisible to the user. And yes, display a response with the result later on.
All of this happens in one method:
if($_POST){
// insertion
}else{
// display no-post environment, if response exists (therefore posted) display response too
}
Something like that...
Sessions is not an option because this is meant to be some kind of API.
update no. 2
Huh, let me rephrase the question a little. Well, it seems that I don't actually need to pass the variable over. What I want to do, is to have 2 different results after POST so on next page load I could know whether the actions in POST has been successful or not. So, what other options are out there without using sessions/cookies/$_GET to get this result?
Currently there is:
temporary database usage: a good option, but I'd like to see different options;
Since you're already using a database it seems like the easiest way to handle this would be to update some kind of temporary table with the information you want based on the post call, then on the page you're doing a header redirect to, read the information in that table. With the constraints you've placed on this (no GET, SESSION, Cookie or Javascript) you're not going to be able to maintain a variable when you redirect from one page to the next.
So leverage that database and take the work off of PHP. Initially I was going to suggest utilizing cURL but I don't think that will help here (though you may want to look it up if you're unfamiliar with it, as it might be what you're looking for)
HTTP is a stateless protocol; thus, there's not going to be an easy, built-in way to add state. That said, I think sessions are the best way to accomplish what you want to do. If what you're doing isn't in the browser, maybe try some sort of session key setup (like the Facebook platform uses).
On one of my pages I have users queue up search terms to be to queried from a 3rd party API. As they're building the queue, my site is making the queries in the background (through ajax) so I can cache the responses, saving them time when they submit. I store a session variable $_SESSION['isloading'] as true during the time that the background queries are running, and its false when they're done.
When they submit, the results page waits for $_SESSION['isloading'] to be false before querying the cache for result. Meanwhile they're shown a progress wheel.
Is there a name for this technique of using a session to locally "lock" a user before proceeding to the next step in the code? I came up with this approach on my own and was wondering if it is a common (or good) solution to this problem, and is used elsewhere.
Putting it in $_SESSION will be a wasted effort. Been there, done that and it didn't work out.
You will be much better off if you provide your "search query string" in as a $_GET variable for your XHR ( marketing people call it - Ajax ).
Off the top of my head, this sounds a little similar to the way some older forum software performs forum searches in the background, and the visible page does a repeated refresh until the background search is complete.
I don't think there's a name for it; I'm also note entirely convinced that it's a great solution. As stevecomrie pointed out, you're going to run into difficulties with concurrency (unless the session variable's name is unique per search query).
I'd instead recommend an XmlHttpRequest (as teresko points out, it's not really called "AJAX", ugh!) and you can handle the "waiting" quite simply with Javascript.
I asked about this on IRC (Hat-Tip to ##php on freenode), and they suggested I just make the search form and search results one page. Then, when they're done entering their searches the view would change rather than submitting to the next page. This would remove the necessity of keeping track of an 'isloading' state. This seems like a better approach to me, are there any problems with it?
I've got a website that has a form that the user can type in. I want it to be the replacement for a 3rd party website (Autotask) form with the same fields. Normally I'd just have the action in my form go to where the 3rd party's form points and then have all the same id/name values for my own fields, but there are several problems with this:
Autotask's forms aren't just simple muli-field forms. They import at least 15 Javascripts that make something magic and unidentifiable happen, and they are incredibly difficult to read and understand. So that causes two problems, one that the form takes a very long time to load (5 seconds or so for 4 fields), and two is that if Autotask changes anything at all I'll need to redo the whole form (very tedious and crapshoot-y, and I already have needed to do it twice).
In order to make the load time more transparent, I put my copy of the Autotask form within an iFrame. That way the rest of the website can load separately from the expensive number of scripts I've got to include with Autotask's logon process.
Ideally what I want to be able to do is to just have those 4 fields on my site with whatever name and configuration I want, then send that POST data to my own PHP script, which will automatically (and transparently) submit that data directly through Autotask's forms in the proper fields. If I need to make the id/name match, that's okay. I can use HTML, Javascript, and PHP on this site.
EDIT:
Autotask has built-in GET handlers for their logins. You'll notice that you have a client ID at the login (it will be the "ci" variable in the URL). If you send a GET request with the client ID there and variables for "username" and "password," then it Autotask's login page will immediately forward you to the client page, given a successful login.
I think a lot of people would advise against this in general, as you're kind of hacking the functionality of someone else's app. In this case I only advise against it because they (Autotask) have an outward facing API already. http://www.autotask.com/press/news_and_press_releases/071006.htm I think that you'd be better off just utilizing it and developing something that functions pretty well within the constraints of their system.
one really round-about way of doing it is have your page load a form with some generic id/names. have a php script that scrapes their page for the correct id/names, and the ajax them into your forms.
That way you avoid having the load time of iframing their content in, or scraping their page on your initial page load and they change the id/names you'll always have it up to date.
I could write up a big post that explains on this, but really I think this is a perfect time to let someone else's words do the work.
Autotask's forms aren't just simple muli-field forms. They import at least 15 Javascripts that make something magic and unidentifiable happen, and they are incredibly difficult to read and understand.
Sounds like anti-spam measures to me? If so, then they will probably change over time.
So: follow NateDSaint's advice!
As a follow-up, it turns out that with Autotask they have GET handlers so you can just send information via GET. Problem solved.