Look Ma, Cross-Domain Scripting!
Ajax, as I've stated time and time again, is sweet. So what is problem? XMLHTTPRequest requires that the called scripts that execute server side and return information to the client must reside on the same domain. This has irked me time and time again during my exploration and experimentation of the Web 2.0 world.
Enter JSON Web Services and dynamic script tags. This beauty allows for Ajax-like communication across domains without requiring page loads. Right right right...so how do you use it? Read on...
First, lets clarify what JSON (JavaScript Object Notation) is. Wikipedia explains that JSON is just a way to structure object data in a way that is easily interpreted...primarily with JavaScript. Here's some examples from Wikipedia:
JSON Example:
-
bork({"menu": {
-
"id": "file",
-
"value": "File",
-
"popup": {
-
"menuitem": [
-
{"value": "New", "onclick": "CreateNewDoc()"},
-
{"value": "Open", "onclick": "OpenDoc()"},
-
{"value": "Close", "onclick": "CloseDoc()"}
-
]
-
}
-
}});
Which is the same as this XML Example:
-
<menu id="file" value="File">
-
<popup>
-
<menuitem value="New" onclick="CreateNewDoc()" />
-
<menuitem value="Open" onclick="OpenDoc()" />
-
<menuitem value="Close" onclick="CloseDoc()" />
-
</popup>
-
</menu>
So...if JSON just the data representation part of things, how does it work similarly to Ajax?
Now we're getting into the Web Services side of things. The quick answer: When you dynamically create <script> tags on a page, the JavaScript source is executed immediately. Now, as most experimental web developers may well know, you can reference remote JavaScript source in a <script> tag. Which means....if you dynamically create a script tag that references a source on another domain, and that source outputs JSON, you are as good as gold!
Here's the step by step: (I use a JavaScript Object I found over at Dan Theurer's Blog for the dynamic adding of script elements...it helps avoid duplicate script tags).
First, lets make the remote file that outputs JSON. (obviously, most cases will have the data dynamically generated...but I'll use a static example as the generation of this data is trivial)
file: remote_file.php
-
<?php
-
echo 'bork({"Image": { "Width":500, "Height":250, "Title":"Giant Cow", "Thumbnail":{"Url":"http://someurl.com/image/1234", "Height": 75, "Width": 150}}});';
-
?>
Here's the html file we want the user to see/interact with:
file: client.html
-
<script src="js/jsr_class.js" type="text/javascript"></script>
-
<script type="text/javascript">
-
function addScript()
-
{
-
var obj=new JSONscriptRequest('http://someurl.com/remote_file.php');
-
obj.buildScriptTag(); // Build the script tag
-
obj.addScriptTag(); // Execute (add) the script tag
-
}//end addScript
-
-
function bork(data)
-
{
-
var text='';
-
-
if(data==null)
-
alert('error');
-
else
-
{
-
text='Image Title: ' + data.Image.Title + '<br />';
-
text+='Width: ' + data.Image.Width + '<br />';
-
text+='Height: ' + data.Image.Height + '<br />';
-
text+='Thumbnail Data: ' + data.Image.Thumbnail.Url;
-
text+=' (' + data.Image.Thumbnail.Width + 'x' + data.Image.Thumbnail.Height + ')<br />';
-
}
-
document.getElementById('output').innerHTML=text;
-
}//end bork
-
</script>
-
<a href="#" onClick="addScript(); return false;">Click to Get Stuff</a>
-
<div id="output"></div>
-
</body>
-
</html>
Thats all there is to it! Simple and slick.
Discuss This Article
|
|
23 Responses to “Look Ma, Cross-Domain Scripting!”
-
Edward Clarke
Posted: Feb 7th, 2006 at 3:25 am1 -
Bill Wilson
Posted: Mar 7th, 2006 at 1:44 pmReply to this comment.I’m looking at your code and it doesn’t explain exactly how this works, it just provides us with code to use. I’m curious as to what makes JSON work and what differences JSON has from XML. Is there any draw-backs or negative effects of using your solution? Is it a hack that will be fixed in the future?
2 -
pingback:
Posted: Mar 10th, 2006 at 10:07 amBorkWeb » Blog Archive » Ajax; Templating; and the Separation of Layout and Logic Reply to this comment.[...] I have often mentioned my process of expanding my proficiency of Ajax. Through my journey I have made a number of wrong turns and hit my share of stumbling blocks. All of that has been a learning experience and I’m learning still. I began fiddling with XMLHttpRequest as many do - blissfully ignorant of the many frameworks that exist to make Ajax super easy. My code was bloated with some neat…’features’ (pronounced: bugs). [...]
3 -
pingback:
Posted: Mar 21st, 2006 at 7:37 pmNo Sheep » Behaviour, Return of Clean HTML Reply to this comment.[...] As we’ve begun adopting Ajax, JSON, and similar JavaScript heavy technologies a problem quickly arose. Suddenly our clean HTML was being cluttered with tons of script tags, onclicks, and other various event handling functions. Trying to extract this logic back out of the HTML was a definite desire for us. [...]
4 -
pingback:
Posted: Mar 24th, 2006 at 8:54 pmBorkWeb » Practicing What I Preach Reply to this comment.[...] MasterWish was built using SAJAX as the tool of choice for Ajax communication but as I’ve mentioned in the past, I am a Prototype convert. My knowledge of Ajax, JSON, and general application structure has been morphing so much in recent weeks that I have held off in completely revamping the wish list site. [...]
5 -
pingback:
Posted: Mar 29th, 2006 at 3:38 pmBorkWeb » The Case For JSON: What Is It and Why Use It? Reply to this comment.[...] After my post titled Look Ma, Cross Domain Scripting! a while back, I received a comment that was seeking more information. The commenter posts: I’m looking at your code and it doesn’t explain exactly how this works, it just provides us with code to use. I’m curious as to what makes JSON work and what differences JSON has from XML. Is there any draw-backs or negative effects of using your solution? Is it a hack that will be fixed in the future? [...]
6 -
bob
Posted: May 8th, 2006 at 4:00 pmReply to this comment.crap man….at least put up a working sample so we can view. I have no idea how this really works.
7 -
skUte
Posted: Oct 13th, 2006 at 6:24 amReply to this comment.Your example did not work for me. The other example from yahoo only works for me in firefox, IE returns nothing. Is JSON not cross browser ?
9 -
cornwell
Posted: Oct 18th, 2006 at 12:31 pmReply to this comment.wow - works great although i did have to change the sample page to get it to work
note you must have a parameter os some type like ?a=b because the JSON script adds a timestamp to the end to prevent caching ….. “‘&noCacheIE=’ + (new Date()).getTime();”
var obj=new JSONscriptRequest(’http://www.netlert.com/includes/crossdomaintest2.php?a=b’);
however don’t understand this part
“….if you dynamically create a script tag that references a source on another domain, and that source outputs JSON, you are as good as gold!”i just created a simple php page like so
bbbbb”);’;
?>and added a function to my page
function test(a, b){
var e = document.getElementById(’output’);
e.innerHTML = a + ” ” + (new Date()).getTime();
e.innerHTML += b;
}so I don’t see why you have to use JSON notation - anyway, i tested this on the major browsers - netscape 6.2 and up - firefox - opera, ect and it worked fine.
However I created a loop at the bottom and there is a slow memory leak :(
function loop(){
addScript();
setTimeout(”loop();”, 1000);
}
setTimeout(”loop();”, 1000);actually i take that back - I made the obj var global and in my test script I do a obj.removeScriptTag(); and it seems to fix the memory leak.
anyway thats my input - this is awesome!!!
10 -
cornwell
Posted: Oct 18th, 2006 at 12:38 pmReply to this comment.wow - this is great - you have to modify the test to get it to work
you have to add a parameter on the end of the JSON object like so
obj=new JSONscriptRequest(’http://www.netlert.com/includes/crossdomaintest2.php?a=b’); because the script adds a timestamp to prevent caching ‘&noCacheIE=’ + (new Date()).getTime();The other thing is if you are making a lot of calls over time there is a memory leak so you have to make the JSON object global so you can call obj.removeScriptTag();
var obj;
function addScript()
{
obj=new JSONscriptRequest(’http://www.netlert.com/includes/crossdomaintest2.php?a=b’);
obj.buildScriptTag(); // Build the script tag
obj.addScriptTag(); // Execute (add) the script tag
}however i don’t understand this part “if you dynamically create a script tag that references a source on another domain, and that source outputs JSON, you are as good as gold!”
I just created a simple php page like so
bbbbb”);’;
?>and added my own function
function test(a, b){
var e = document.getElementById(’output’);
e.innerHTML = a + ” ” + (new Date()).getTime();
e.innerHTML += b;
obj.removeScriptTag();
}works great - this is awesome thanks!
11 -
niels marsman
Posted: Nov 20th, 2006 at 3:07 amReply to this comment.I’ve got a question about security.
How can I, when U include a PHP page that generates JSON, restrict it to just one website?
So no one can include the page, just by viewing the source and copy the uri.
I tried it to check whether the HTTP_REFERER is the same as a var set in the PHP file.
But i found that the HTTP_REFERER is not always set, you can disable it in your browser settings..anybody got an sollution?
btw: nice script!
12 -
niels marsman
Posted: Nov 23rd, 2006 at 5:50 amReply to this comment.I understand what you are saying, the only problem i have now is: how can i add more sites, every site is a single user and the application is only ristricted to their site. Now the problem with your code is that everyone could just copy and paste it in their website and use the script intended for someone else. The script is like a external login, you login in your website and then a admin page is loaded from another server where the user can manage some hosting/website updates for his site/hosting.
14 -
steve-0
Posted: Dec 24th, 2006 at 7:47 amReply to this comment.Now the problem with your code is that everyone could just copy and paste it in their website and use the script intended for someone else.
So that’s the point of the workaround, right (to take advantage of legal operations in a browser to allow you to load scripts from other sites dynamically)? If I understand you correctly, and you’re trying to restrict people from linking to your scripts from offsite (which is kinda not really on tt) in any surefire fashion; what you are looking for is something like a perl handler on mod_perl that serves the bodies of scripts for you. Then before the handler decides if it will write your script to the browser or write “Screw you hax0r”, you have access to the whole host of apache’s information — you can then always see the full URI for the script and filter accordingly.
Oh also — kudos on this script too. =)
15 -
pingback:
Posted: Sep 21st, 2007 at 10:45 amGUJS - Grupo de Usuários Javascript » Arquivo » Ajax cross-domain com JSONP Reply to this comment.[...] Look Ma, Cross-Domain Scripting! [...]
16 -
pingback:
Posted: Oct 14th, 2007 at 10:47 pmRead. « grahaNa 17 -
Boyke
Posted: Mar 15th, 2008 at 7:03 pmReply to this comment.Hi, is there any way to send post variables to the php (server side) script?
18 -
poker net www online poker net
Posted: Apr 5th, 2008 at 2:09 amReply to this comment.In addition poker heads up online buy coffeehouse ring joint line four same day cash advance loan street seven corner deuces amount fold download giochi juice deck game round fill!
19 -
pingback:
Posted: Jun 5th, 2008 at 4:05 amjquery json remoting Reply to this comment.[...] JSON. ….. 1 - javascript pure cross-domain scripting 1 - ajax jquery json cross domains …http://borkweb.com/story/look-ma-cross-domain-scriptingSedna RSS jQuery.infojson parser doesn’t output - pedalpete Discuss jquery mailing-list … DWR for [...]
20 -
Tracy
Posted: Jun 27th, 2008 at 5:28 pmReply to this comment.I cannot seem to get your example working. Everything is error-free, but my callback function (bork) never gets visited. I’ve copy/pasted your client code exactly, changed the remote URL to this: http://www.twonkyvision.com/test.php (no that’s not a valid software license format), and made the first line in bork() to just send out a simple alert box. But my alert never gets visited, but no javascript errors showing up in my console.
Am I missing something? My client box is MS IIS, but my server box is LAMP, would that be a problem?
Thanks!!
21 -
pingback:
Posted: Aug 30th, 2008 at 7:32 amXSS Reply to this comment.[...] B was running from host A and doing an XHTTPRequest request to host B. So what to do? Well I found this article on using JSON to do cross domain scripting (and here is even more background) but it [...]
22 -
Kyle Simpson
Posted: Sep 27th, 2008 at 11:56 amReply to this comment.The problem I have with a technique like this is the amount of hoops you have to jump through to control who can and cannot get to content cross-domain.
Enter: flXHR (pronounced flex-er) http://flxhr.flensed.com/
It’s a javascript+flash combination that uses an invisible swf instance to act as a proxy and leverage Adobe’s server-opt-in model for crossdomain.xml policies to allow authorized cross-domain communication.
flXHR implements an identical API to the normal native XHR, which makes it a super-easy drop-in replacement, meaning it can effortlessly be used with any number of various JS frameworks that already know how to speak XHR API.
It’s client-side cross-domain, without all the hassle, and with much more reliability.
23



Good example of scripting around browser securities. Should see greater use of this in the future. It still limited by browser support though.