I feel like I’ve run into this issue so many times and either fixed it by accident or came up with some other solution in order to do the same thing. This time I cam to a conclusion that I understand and hopefully other people can use.
You create an flash app for the web which loads in data from a variety of other external sites, such as thumbnails from an aggregated feed using a 3rd party API and it works swimmingly while you’re testing locally. As soon as you put it on a remote server, you get a Flash Player security error, perhaps something like:
SecurityError: Error #2122: Security sandbox violation: LoaderInfo.content:http://staging.site.com/project/Main.swf cannot access http://www.website.com/image.jpg. A policy file is required, but the checkPolicyFile flag was not set when this media was loaded.
at flash.display::LoaderInfo/get content()
Depending on if you’re ready for this error or not, you may not get a popup and can fail silently.
Why This Happens:
This is happening because you don’t have your policy files set up on your server and your swf is “illegally” trying to access data from another domain. This is actually a good thing since it stops potentially dangerous files from doing bad shit to your project/server/network/computer. But you want to ALLOW access to these different domains since that’s a big part of your project, right? The solutions are actually very easy to implement, just sometimes a pain in the ass to figure out.
Depending on the project and how wide-spread and prominent it will be on your website and if other projects will need the same sort of access on your server, you may want to allow the entire domain access to the external domains or just one individual project.
For an entire domain
All you have to do is place a crossdomain.xml file is the root of the server where the project will reside. The crossdomain file will look similar to this:
Replace the * with a specific domain if you don’t want to allow access to all sites. This works because the flash player automatically looks for a crossdomain.xml file when it is asked to load any file in a different domain. It checks to see if it should allow the file based on which domains are specified in the file. If it doesn’t see this file or a domain isn’t listed, or * isn’t specified, it will throw an error and won’t allow the file to be loaded into your app.
For a sub-domain
Sometimes the above solution isn’t appropriate, especially for a website that can potentially house many different projects that have different rules about what is can and should allow. This solution involves a few extra steps, but is still pretty easy.
You still need to add a crossdomain.xml file to the root of your server, but instead of allowing all domains to be accessed, you want to tell it that it should allow crossdomain policy files to be set elsewhere on the server. This is what the crossdomain.xml file would look like instead:
Create a crossdomain file somewhere else on the server that makes sense, such as where your project exists. This will look a lot more like the original file. In fact it’s exactly the same, unless you want to change the domains that you want to allow for this specific project.
Make note as to where you are putting this file, since you will be specifying this actual xml file as the one to look at for cross domain access (ie: http://staging.site.com/project/crossdomain.xml).
The next 2 steps involve actually adding some as3 code and republishing.
Specify the policy file that should be loaded instead of the one in the root. This should be done before trying to actually load anything. I normally place in the document class as one of the first things that should be done.
Don’t forget to import flash.system.Security.
Go to where you are trying to load the external data and create a LoaderContext instance.
var context: LoaderContext = new LoaderContext();
context.checkPolicyFile = true;
As noted from adobe’s website, what checkPolicyFile does is specifies whether a cross-domain policy file should be loaded from the loaded object’s server before beginning to load the object itself.
Then you will pass that context as an argument when you go to actually load the file, as seen below.
imgLoader = new Loader();
iimgLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onImageLoad, false, 0, true);
imgLoader.load(new URLRequest(thumbUrl), context);
This article got me on the right foot: http://stunnedgrowth.livejournal.com/4540.html
More about LoaderContext: LoaderContext