When requesting (ht|x)ml with ajax you can only send requests to the same domain. But if you request JSON you can send it to any domain. Why?
I'm told it's for security but why would a website do something malicious via ajax rather than just directly if that makes sense.
Check out this wikipedia article.
The reason why JSON is 'safe' is because you have to pass it through a callback. The remote site will run return JSON and your javascript library will not just run it blindly but try to pass it to a function you specify, like jsonpCallback( response ). Since you aren't running the remote code directly much more is under your control and all is mostly well in the world.
The reason it's called JSONP has actually little to do with JSON itself. Doing a cross-domain ajax request is as simple as adding the <script src="http://url.com/data.js></script> tag to your HTML web page; this is the base concept of JSONP and cross-domain ajax.
What happens is that the data.js file is interpreted by JavaScript. This gives us the ability to get data from that data.js file (which is located on another domain), if for example it loads a function that is available in the current scope.
Here is an example of why someone would hack an AJAX request.
https://blog.codinghorror.com/preventing-csrf-and-xsrf-attacks/
http://directwebremoting.org/blog/joe/2007/04/04/how_to_protect_a_json_or_javascript_service.html
Injecting JSON directly in your page is not secure at all.
You offer to the loaded scripts full access to the resources in your page(data, cookies, logic).
If the injected code is malicious, it can run actions on your server, post back data to their server(POST is allowed cross domain, not the response but your data are sent anyway), etc...
We're building a web app that makes a heavy use of cross domain accesses.
To solve this problem, we came with a rather simple JSONP sandboxing solution.
Related
I'm working on the project where the client has the back-end code in ServerA, and my front-end code, which is supposed to talk to back-end via AJAX requests is on ServerB, and they are in different domains. Because of the same origin policy, I'm not able to make those requests successfully (neither POST nor GET). Is it possible to enable it somehow without changing the back-end code to handle the JSONP? eg., white list that particular domain, or something?
I tried to emulate this in my local network where the back-end code is running on 10.0.1.4 (different machine), and I'm accessing it from localhost (apache), but couldn't figure out anything that doesn't require using jsonp. When calls are made, I'm not even seeing anything in the logs in the back-end, but it works fine from the REST client and by just loading the URL for GET requests. How are public API requests implemented that are not using JSONP?
I need at least one method (POST or GET) to work. Thanks.
Is it possible to enable it somehow without changing the back-end code
to handle the JSONP? eg., white list that particular domain, or
something?
Yes, you could write a server side script on your domain that will serve as a bridge between your and the remote domain and then send an AJAX request to your script.
Don't expect miracles. If you don't have control over the remote domain you are busted. The same origin policy restriction that's built into browsers for security reasons busts you. Well, you could always write your own browser that doesn't implement this policy, but I think you get my point.
Common workarounds include JSONP and CORS but they involve control over the remote domain. If you don't have control then read the my previous sentence as well as my first sentence.
Here's a nice guide I invite you consulting that covers some common techniques allowing to achieve cross domain AJAX with jQuery. Then adapt the one that fits best your scenario. And there's always the heavy artillery solution that involves bridging the 2 domains with a server side script which works bullet-proof in 100% of the cases if none of the other workarounds help you.
Is it possible to enable it somehow without changing the back-end code to handle the JSONP? eg., white list that particular domain, or something?
Hmmm, mostly no. You must allow JSONP or "white list" things via CORS (which is very easy to do). Or you can use YQL as a cross-domain proxy.
Three solutions posted here:
http://devlog.info/2010/03/10/cross-domain-ajax/
I've tried the third option since it just worked for me.. and I didn't have to go through any extra stress as it just handled things just like a regular ajax call.
Updating answer as this was posted 2 years ago:
LINK ABOVE NO LONGER WORKS.
Server side proxy:
the old page also talks about using a server side proxy, which means your server makes a call to another server, grabs all the data and sends it off to a page resting on that server. There is no problem for one server to fetch data from another server. So then your page can make a regular ajax call to that server. I didn't go with this option as it required more manual labor. So I'd suggest going with the option detailed here:
JSONP with jQuery
Make sure the provider supports JSONP.
Set the dataType option to jsonp, and if the provider uses a different GET param other than 'callback', specify the jsonp option to that parameter name.
$.ajax({
// ... Use the AJAX utility as you normally would
dataType: 'jsonp',
// ...
});
jQuery will generate a unique callback name for this request (something like json1268267816). Thus, the reply from a web service would be something like:
json1268267816({'uid': 23, 'username': 'Chroder', 'name': 'Christopher Nadeau'});
But jQuery handles it all seamlessly, so you as the developer just handle it like a normal AJAX request using the same jQuery success/failure/complete callback hooks.
Drawbacks:
The first limitation to this method is that you have to rely on the provider to implement JSONP. The provider needs to actually support JSONP -- they need to wrap their JSON data with that callback function name.
Then the next limitation -- and this is a big one -- is that JSONP doesn't support POST requests. Since all data is passed in the query string as GET data, you are severely limited if your services require the passing of long data (for example, forum posts or comments or articles). But for the majority of consumer services that fetch more data than they push, this isn't such a big problem.
However,
Using a library like jQuery that supports JSONP, these details of inserting the special script tag and creating the special callback function are all taken care of automatically. Using a JS library, usually the only difference between JSONP and real AJAX is that you enable a 'jsonp' option.
I have an application on one domain which needs to get data from an application on another domain.
I would like to use an iframe based cross domain ajax tool such as porthole.js to implement the following:
My application loads a page on the other server in an iframe.
A message is sent using porthole to the iframe.
The page on the other server checks to make sure the calling url is valid, and reads in the url of the ajax request it will make from the message.
The remote page then uses the passed url to make an ajax request.
The results are passed back to my application.
This solution lets me use the remote json data without systematically altering all of the services, which are built and managed by another team. If it doesn't work, I would work with them to use a system that uses porthole.js or jsonp for cross domain scripting.
The point that concerns me, though, is step 4. Does this count as an ajax call from the remote document inside the iframe, which would be able to make ajax calls against it, or does it count as a call from the outer window, which can't use ajax to call that domain?
Jeez, just use CORS. It's a one-line change to the web-server config.
Is it possible (and if so, what's the most secure way) to read a JSON file from a subdomain such as somesubomain.maindomain.com in a JS script residing in maindomain.com, another.maindomain.com etc?
Thanks!
Have a look at how document.domain works: https://developer.mozilla.org/en/DOM/document.domain
Another solution would be make your json file a JavaScript file (jsonp-style) which calls a function so it can be embedded using a script tag which does not have same-origin restrictions.
Your not supposed to due to the same origin policy enforced on all browsers, but you can... Check out this explanation of cross domain ajax requests.
http://alexsexton.com/?p=154
JSONP is what I found to be the easiest to work with for this type of stuff.
I do this two ways:
Have your server make the call on behalf of your client. What I mean by that, is take the call you were going to make from the browser, and make it a web service on the server. Then have your client call your webservice, which will then make the call and return the response. This allows you to inspect what's being sent back and forth.
Use JSONP. Their server must be configured for this, and I'm not sure there is any added security..
I'm trying to write a utility in my blog system as a post. The limitations are that I can not run any server side code. I can only run client side (JavaScript) code. I would like to send a request to an external domain and parse that result.
For example, based on how people use my utility, I would want to be able to get the HTML of a page such as http://example.com/getPage.html?page=A, which might contain:
<html>
...
<body>
...
<table id="targetTable">
<tr><td>Some Data</td></tr>
<tr><td>Some Data</td></tr>
<tr><td>Some Data</td></tr>
</table>
... which I would store in a JavaScript string and then query to find the data I want.
I want to query this page from an external domain (i.e. my script is not running on http://example.com, nor am I affiliated with http://example.com) using client side code only.
I'm using jQuery and it says that the jQuery.get() method would not work due to the same origin policy. Is there any way to do what I want some other way? For example, loading an iframe then reading its html property somehow?
You might want to take a look at JSONP and the more recent CORS. Using these technologies still doesn't guarantee that you'll be able to do what you want using only Javascript and no server side code...
I'm afraid that is impossible. You can work around it using a convention called jsonp, but that will only be able to retrieve json objects (even if those of course can contain html-strings). But a server can only respond to a jsonp request if it has builtin support for it.
The most straightforward workaround for your problem would be to create a tiny server that gets html pages and returns json-data. Then you can send your ajax calls to that server (like this: http://www.yourserver.com/?page_to_get=http%3A%2F%2Fwww.example.com%2FgetPage.html%3Fpage%3DA), let it fetch data from example.com and return it to your client side script as json.
Just to strengthen my argument, a piece quoted from jQuery's AJAX page:
Due to browser security restrictions,
most "Ajax" requests are subject to
the same origin policy; the request
can not successfully retrieve data
from a different domain, subdomain, or
protocol.
Script and JSONP requests
are not subject to the same origin
policy restrictions.
You can load an iframe from another domain or make POST calls to another domain.
Luckily for our security but unfortunately for your problem, you can't read anything with Javascript due to the Same Origin Policy.
If you can't get any cooperation from the other domain. eg: with JSONP enabled or a window.postMessage then the only solution you have is to use a web server as a proxy.
The server that delivers your page or a free(if your trafic isn't huge) instance like Google App Engine, where you have a hand on.
You call this server in ajax, JSONP or an iframe + window.postMessage with a generic service that will fetch the page content and deliver it to the browser.
Something I find really confusing, is why are AJAX requests limited to the same domain? What is the reasoning behind this?
I don't see any problem with requesting files from external locations, also servers making XMLHTTP requests seem to get and post to external locations fine.
Picture this :
You come on my fabulous website www.halfnakedgirls.com. You have fun watching what looks like technical documentation on human physiology, but behind your back, some lines of JavaScript are executing some request to another domain, let's say www.yourpaypallike.com.
Requests like http://www.yourpaypallike.com/account/transfer?to=badguy#evilwebsite.com&amount=984654 or http://www.mymailprovider.com/mails/export?format=csv.
Do you now see why it is forbidden ? =)
Tom, it is not "Ajax request limited". AJAX is based on JavaScript. For security reason JavaScript is prohibited access on cross domains. If you really want to do cross domain Ajax, you can do a hack.
YourPage(Ajax) ----> YourServer ----> ExternalDomain
You can call a page in your server using Ajax, Your domain will call to external domain using server side , and get the result then return to you as Ajax response.
Of course the request done to the ExternalDomain server will be called WITHOUT sending cookies for ExternalDomain that reside in your browser's memory. That's because the request is done by your server and not your browser.
It's for security purposes - if a website could execute AJAX calls to any domain they wanted on the client side, it poses a serious risk.
There are ways around this though - you could have your AJAX call a PHP script on the same domain, which in turn can call a script from another domain and return it. This wouldn't be using the browser as the communication medium though, it'd be using your web server.
Here is some information to satisfy your question:
http://en.wikipedia.org/wiki/Same_origin_policy