Safe Way to Send POST Request via Javascript - javascript

I'm currently sending POST requests to a PHP file of mine via a button with the following function:
function buttonFunction() {
$.post("http://ipaddress/core/file.php",{username:username, password:pword, coins:coins}, function(data) {
// Stuff
});
}
However, I recently found out that if the file process/PHP script is still running (trying to obtain the resulting data/response), and the user refreshes the page, the PHP process would still be running on the server. Also, if the user then decided to click the button again (after refreshing), there would be TWO PHP proccesses running from the same user on the server (that is, if the first one was still running):
Javascript Abort POST Request on Retry/Refresh (HIGH CPU Usage)
However, I came across sending POST data with XMLHttpRequest with Javascript:
Send POST data using XMLHttpRequest
So let's say I send my POST request this way, would it be safe to say when the user refreshes/closes out of the page, the PHP execution ends?
function buttonFunction() {
var http = new XMLHttpRequest();
var url = "get_data.php";
var params = "lorem=ipsum&name=binny";
http.open("POST", url, true);
//Send the proper header information along with the request
http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http.setRequestHeader("Content-length", params.length);
http.setRequestHeader("Connection", "close");
http.onreadystatechange = function() {//Call a function when the state changes.
if(http.readyState == 4 && http.status == 200) {
alert(http.responseText);
}
}
http.send(params);
}
However, if this also does not work, how can I fix this issue (multiple scripts running in the background from the same user)? Whether that fix be in the PHP file or in the JavaScript itself, any help would be appreciated.
Edit 1:
Possible Solution?
What if I use XMLHttpRequest and abort the request before the page unloads?
window.onbeforeunload = function(event) {
http.abort();
};

Related

XMLHttpRequest refresh only when a change on database is detected

My Ajax function is refreshing all the time, and I'd like it to just refresh when a change in a database is detected. Is there a way of doing this?
MY CODE:
function ajax(){
var req = new XMLHttpRequest();
req.onreadystatechange = function(){
if (req.readyState == XMLHttpRequest.DONE && req.status == 200) {
document.getElementById('chat').innerHTML = req.responseText;
}
}
req.open('GET', 'chat.php', true);
req.send();
return false;
}
setInterval(function(){ajax();}, 100);
If you want to have server-push, you can use either Server Sent Events or a Websocket, instead of polling from the client with XMLHttpRequest.
You would have to detect a change in the database on the server side, and then push the change to the webpage using SSE or a websocket, or, alternatively, send a flag that there has been a change, and then pull the change from the webpage using XHR as you are doing now.
I don't know enough about your set-up to provide you with code examples, but there are plenty of examples on the interwebs showing how to do this, with either SSE or a websocket.

Post to and visit a URL in Javascript

I'm trying to:
Post a JSON object to a URL and visit it at the same time.
Set the content-type and accept headers
I'm working with an old source base (asp classic / vb). Ideally, if I can do this in javascript it would be wonderful!
Constructing the js call with headers and data is simple with XHR:
var xhr = new XMLHttpRequest();
var url = "url";
xhr.open("POST", url, true);
xhr.setRequestHeader("Content-Type", "application/json");
var data = JSON.stringify({JSON DATA});
xhr.send(data);
However this is an async call and I can't seem to find a way of making it actually visit the URL in the browser.
The alternative is to create an form and append it to a HTML entity before using javascript to submit it. This time is post the data to and visits to the URL.. however, I don't have control over the headers.
So back to my questions. Can I post to and visit a URL in Javascript?
Given that visiting an URL in the browser is a GET request, and you want to POST at the same time, NO you cannot.
Why do you need to post and visit?
You could post your data and in the callback (once the post request is done) load the the page.
No.
The closest you could come would be to:
Use Ajax to make the request
Use DOM to modify the current page with data from the response
Use the History API to update the URL in the address bar
Changing the server side code to expect regular form encoded data and then submitting a regular form would probably be the simplest approach to solving the problem.
You are using XHR, and if you want to manage it from javascript... Add onreadystatechange property to your xhr (this function will be fired when your server response), and in this function redirect using window.location.href
var xhr = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
// Here redirect, with params if you need to
window.location.href = "https://stackoverflow.com?name1=value1&name2=value2";
}
};
var url = "url";
xhr.open("POST", url, true);
xhr.setRequestHeader("Content-Type", "application/json");
var data = JSON.stringify({JSON DATA});
xhr.send(data);

Security of GET vs. POST when using Ajax

I used ajax to send the data. I was successful in implementing it using two different approaches:
1) Using method 'POST' and sending data in send() method by setting requestheader.
var xmlHttp = getXMLHttpRequest();
var url="login.do";
xmlHttp.open("POST", url, true);
xmlHttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xmlHttp.onreadystatechange = function() {
if(xmlHttp.readyState == 4) {
// Done. Do nothing.
}
}
xmlHttp.send("userName=xyz&password=abc");
2) Using method "POST" and appending parameter values in the URL as:
var xmlHttp = getXMLHttpRequest();
var url="login.do?userName=xyz&password=abc";
xmlHttp.open("POST", url, true);
xmlHttp.onreadystatechange = function() {
if(xmlHttp.readyState == 4) {
// Done. Do nothing.
}
}
xmlHttp.send();
Since this is an ajax call, URL will not be visible in the browser window, so I wanted to know which approach is better and why?
Thanks in advance
Here is W3 recommendation for you.
That pretty much says what exactly you need to do.
Authors of services which use the HTTP protocol SHOULD NOT use GET based forms for the submission of sensitive data, because this will cause this data to be encoded in the Request-URI. Many existing servers, proxies, and user agents will log the request URI in some place where it might be visible to third parties. Servers can use POST-based form submission instead.
Though it is saying post, internal meaning of it is to keep the URL clean.
Apart from the given two ways, if I were you, I prefer clean codes (imagine 10 query param).
var data = new FormData();
data.append('userName', 'xyz');
data.append('password', 'abc');
var xmlHttp = getXMLHttpRequest();
var url="login.do";
xmlHttp.open("POST", url, true);
xmlHttp.onreadystatechange = function() {
if(xmlHttp.readyState == 4) {
// Done. Do nothing.
}
}
xmlHttp.send(data);
Putting data into the URL's query parameters doesn't make it a GET request. A POST request is a POST request; the difference is between sending data in the URL or sending it as POST body. There's no fundamental difference between both in this case, the data is equally (non) visible for anyone who cares to look.
The only arguable difference in security is that the URL will likely be logged by the server and/or proxies, while body data usually isn't. But then again, you're already sending the data to the server you presumably trust, so even that doesn't make much of a difference. And the server(s) could be logging the body as well if they wanted to.
Semantically I'd send the data in the POST body, but that's not because of security.

Ajax Post to a different domain url , redirect to another url

I am supposed to call a third party vendor - Cybersource using their silent order post. The problem is that I have an accordion page which has 3 panes, Account creation, Service address and billing (on third pane).
I am trying make an ajax call from [http://mydomain/billing][1] TO [http://cybersource/silentorderpost/pay][1].
In the post parameters I am setting response url = [http://mydomain/billing][1] this is where CS will send the response back.
When the Ajax post goes from my website to CS website, I do not get a callback but the Cybersource post the response back to my website [http://mydomain/billing][1] and this reloads my whole accordion page which I am trying to avoid. I understand that During an Ajax call, the Ajax expects a response on the same domain as "Called webservice", i.e. my Ajax post expects that Cybersource will post the response on something like [http://cybersource/response][1]. However, CS posts or redirects the response to my website and this is probably the reason, I never get my callback. When the response is posted my whole accordion page reloads and this causes all sorts of issues.
My Code:
function myFunction() {
//document.getElementById("myForm1").submit();
var http= new XMLHttpRequest();
var url = "https://testsecureacceptance.cybersource.com/silent/pay";
var params = document.getElementById("queryStr");
http.open("POST", url, true);
http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http.send(params);
//Send the proper header information along with the request
http.onreadystatechange = function() {//IT NEVER COMES BACK TO THIS SECTION
if(http.readyState == 4) {
alert(http.responseText);
console.log("I came back");
}
}
}
</script>
USING JQUERY:
function myFunction() {
//document.getElementById("myForm1").submit();
var http= new XMLHttpRequest();
var url = "https://testsecureacceptance.cybersource.com/silent/pay";
var params = document.getElementById("queryStr");
var jqxhr = $.post( url, function() {
alert( "success" );
})
.done(function() {
alert( "second success" );
})
.fail(function() {
alert( "error" );
})
.always(function() {
alert( "finished" );
});
// Set another completion function for the request above
jqxhr.always(function() {
alert( "second finished" );
});
}
Any solutions?
var xhr = new XMLHttpRequest();
xhr.open('POST',url,true);
var params = document.getElementById("queryStr");
// you need to call this method:
xhr.send(params);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
//return stuff
} else {
//return stuff
}
}
just like i wrote in my comment, you also need to send your request to the server via xmlhttprequestObject.send() before the readystate can change.
greetings
I found a way out. On my form I added an iframe and now when I get a post response from CS, my page does not reload, instead the response is updated in the iframe.
<form action="https://testsecureacceptance.cybersource.com/silent/pay" method ="post" target="myIframe"> ..... </form>
<iframe src="" name="myIframe"></iframe>
I got the same issue when I integrate cyber source silent post order. I resolved it with form with hidden input fields to create the signature and invisible iframe as the target for my form.
Few things you need to take care while integrating cyber source silent post
1. Make sure you are passing all required fields
2.Generate unique application number and uuid otherwise cyber source will consider it as duplicate request
3.create the signature to make sure input fields are not tampered
4.Dont use ajax to submit the request, in this case the call might ge success but cyber source will not call your customer post back URL that you configured for response.

Load image and remove when authentification is required

I am grabbing some (random) images from a search machine and display them to the users. The problem is: It may happen that some images require a http authentification (username/password). I dont want to have those images... they should be removed without displaying the popup where you can enter the username and password.
Actually I am using simple jquery methods to display my images.
var displayNode = ....
....
var m_img = $("<img />", {src : "...."});
m_img.bind('error', function (e) {
$(this).remove();
});
displayNode.append(m_img);
Now I load the image directly and if an error occurs it will be removed. But.. when server sends back a HTTP (Basic) Authentification flag this is of course not an error. Hence there is an input prompt. When I click on "cancel" the propmt closes, jquery treats this as an error and removes the image.
So.. what is the best way to check if there is authentification and if not display it to the user?
You can make a HEAD request that only returns headers, then check the headers for the authentication header before actually making the request:
The HEAD method is identical to GET except that the server MUST NOT return a message-body in the response. The metainformation contained in the HTTP headers in response to a HEAD request SHOULD be identical to the information sent in response to a GET request. This method can be used for obtaining metainformation about the entity implied by the request without transferring the entity-body itself.
http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
You would use this method to first check the headers, then if OK, get the image. You'll have to test it with your protected resource, I'm not sure what the browser will do when requesting just the HEAD and I don't have a local protected resource to test against (CORS got me on the online resources I was trying to test against). Fiddle:
var basicAuthProtectedURL = 'http://fiddle.jshell.net';
var xhr = new XMLHttpRequest();
xhr.open("HEAD", basicAuthProtectedURL, true);
xhr.onload = function (e) {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
console.log(xhr.getAllResponseHeaders()); //all headers
console.log(xhr.getResponseHeader('Content-Type')); //just the one you want
if (xhr.getResponseHeader('WWW-Authenticate')) {
console.log('I got the authentication header, skip this request.');
} else {
console.log('no header, resource unsecure');
}
} else {
console.error(xhr.statusText);
}
}
};
xhr.onerror = function (e) {
console.error(xhr.statusText);
};
xhr.send(null);
http://jsfiddle.net/5z5bnwgz/
Post back how it goes!

Categories