Recently I needed to use ActionScript’s URLLoader class to retrieve XML from a .NET Web Service, I had no problems until I tried to access the Web Service on a remote machine (i.e. not localhost). When I tried to do this I got the error:
Error #2048: Security sandbox violation: http://localhost/myapplication/main.swf cannot load data from http://remotemachine/webservice.
Not the most useful error message. Searching the web for this error produced a lot of useless results, eventually I discovered that I needed a crossdomain.xml policy file on the remote machine (in the web server root, in this case c:\inetpub\wwwroot) that grants the calling machine access. Where the crossdomain.xml file is in the format shown below (the domain attribute would obviously be replaced with one of the items mentioned in quotes).
<allow-access-from domain="URL" />
<allow-access-from domain="URL Wildcard" />
<allow-access-from domain="Specific IP Address" />
My web service doesn’t know the URL or IP address of the application that will be calling it so I need to use domain=”*” to allow anyone to connect but if I put this in the cross domain policy file that is in the root it applies that access to everything below it not just my web service which is sitting in /webservice. This is obviously undesirable, so the solution seems simple – place the crossdomain.xml file in the /webservice directory.
In the code you would make the following call before making the request with the URLLoader class:
This tells the Flash framework to load a custom cross-domain policy file, simple right? No.
Unfortunately this did nothing, using Fiddler2 I could see that the custom cross-domain policy file was being requested at downloaded successfully, but wasn’t working for some reason.
Again, after searching through many useless results on the web claiming to describe how to fix the problem I discovered what to do, and it’s pretty simple (the links that I found are at the end of this article).
You need to create a cross-domain policy file (i.e. crossdomain.xml) in the root of the web server that allows custom cross-domain policy files and then Security.loadPolicyFile() will actually use the custom cross-domain policy file specified in /webservice.
You have a number of options for restricting how custom cross-domain policy files are used, the easiest and least restrictive is to allow all custom cross-domain policy files, to do this you would used the following:
<site-control permitted-cross-domain-policies="all" />
The option I went with is to only allow policy files with a specific content-type, the master policy file (in the root of your web server) would contain the following:
<site-control permitted-cross-domain-policies="by-content-type" />
Then I set up (in IIS) the extension .policy to have a MIME type of text/x-cross-domain-policy in the directory /webservice on my remote web server and created a file in the /webservice directory called crossdomain.policy with the following XML:
<allow-access-from domain="*" />
If this all seems confusing there is the summary of what you need to do:
- Create a master policy file in the root of the web server allowing custom policy files.
- Create a custom policy file in the directory you want the policy to apply to.
- Call Security.loadPolicyFile(YOUR CUSTOM POLICY FILE) before calling urlLoader.load()
Why Adobe’s ActionScript Language Reference documentation for the Security.loadPolicyFile() method does not mention that you need to allow custom policy files in the master policy file is beyond me.
Cross-domain policy file specification
Policy file changes in Flash Player 9 & 10 – Workflows
Policy file changes in Flash Player 9 & 10 – Meta-Policies
A post on actionscript.org I created regarding my issue
Note: The solution should apply to Flash applications as well, not just Flex Applications, as all the classes mentioned above are actually Flash classes and not Flex classes. (I’m making an assumption here as I’ve never used Flash CSx, but I’m pretty certain it should :))