Why crossdomain.xml is even more than a good thing
For a long time I couldn’t really understand what crossdomain.xml is for. Today, after finishing one the Flex projects I finally figured it out. At least one of two reasons. About 4 years ago Martijn de Visser described one of them – defending your internal network from the attacks. But there is another way reason why crossdomain.xml is good.
Let’s say I’m developing some smart module and I let people download and load it from their domains but there are some specific sites that I want to prohibit. I’m going to use this very simple module to demonstrate how this can be achieved.
<?xml version="1.0"?> <mx:Module xmlns:mx="http://www.adobe.com/2006/mxml" width="100%" height="100%"> <mx:Label text="I'm the protected module" /> </mx:Module>
Suppose that I let http://www.friend1.com and http://www.friend2.com use it but http://www.pron.com shouldn’t be allowed. When I modify the code a bit I will use Flash Player sandboxing to do so.
<?xml version="1.0"?>
<mx:Module xmlns:mx="http://www.adobe.com/2006/mxml" width="100%" height="100%"
creationComplete="onCreated();">
<mx:Script>
<![CDATA[
import flash.net.URLRequest;
import flash.net.URLLoader;
import flash.events.SecurityErrorEvent;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.external.ExternalInterface;
private function onCreated():void {
var url:URLRequest = new URLRequest();
url.url = "http://www.mymodulesfactory.com/check.cfm"
var loader:URLLoader = new URLLoader();
loader.addEventListener(Event.COMPLETE, onComplete);
loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityError);
// this one really doesn't matter
// I'm catching it so the error is not visible
// in the debug player if the user uses it and check.cfm doesn't exist
// check.cfm does not have to exist
loader.addEventListener(IOErrorEvent.IO_ERROR, onComplete);
loader.load(url);
}
private function onComplete(event:Event):void {
// everything is fine, I am allowed to access the domain, ignore
}
private function onSecurityError(event:SecurityErrorEvent):void {
ExternalInterface.call(
"f = function() { alert('you are not allowed to use this extension');"
+ "top.location.href='http://www.mymodulesfactory.com/license.cfm'; }"
);
}
]]>
</mx:Script>
<mx:Label text="I'm the protected module" />
</mx:Module>
Next, I have to create following crossdomain.xml file:
<cross-domain-policy xsi:noNamespaceSchemaLocation="http://www.adobe.com/xml/schemas/PolicyFile.xsd"> <allow-access-from domain="friend1.com"/> <allow-access-from domain="friend2.com"/> <!-- any other friends I like to add in the future go here --> </cross-domain-policy>
The extended example in the conjunction with the above policy file protects this module from being used by the http://www.pron.com. When the module is created it simply calls home, policy file is returned and the module checks if the domain from which it is being used is allowed. Because http://www.pron.com is not on the list SecurityErrorEvent is fired and browser’s alert message pops up. Once the user clicks OK button he will be redirected to the module’s license. This is just a prototype but it should be quite solid.
I’ve created this code outside the IDE so it may have some bugs.
This approach should be very easy to apply in Silverlight as well.