I decided to move this article up the chain in my backlog of articles as I have come across this scenario numerous times on the http://silverlight.net/ forums. This article will give some basic information that has been covered on numerous other sites and times and give some additional insight on how to handle cross-domain issues in enterprise Silverlight service deployments.
Note: This article is pretty long and doesn't really fit well into a blog format (which I find is very limited for effectivily presenting technical ideas on a larger scale). I am going to start moving some of my bigger articles into possible whitepaper format as well.
Contents of this article (Part 1 of 2):
Download link for HttpHandler source code
Silverlight 2 uses services as its primary source of retrieving data across domain boundaries. Once you enter the services and web application domain, you are exposing your content to malicious attacks. One way Silverlight prevents its applications from launching malicious attacks on other sites is through opt-in cross-domain access. This means the site has to say yes in order to receive and respond to requests from a particular domain. This opt-in feature is controlled by a clientaccesspolicy.xml file. If you have done any WCF programming with Silverlight, this should be familiar to you. If not, check the basic information on the MSDN site here.
Suppose that we have a Silverlight application hosted on http://contoso.com/ (means the main/initial XAP file). This application has a service backend that retrieves data from http://mycontososervice.com/. These are obviously on two seperate domains and we have a cross-domain issue. By default, this scenario will not work. We need to create a clientaccesspolicy.xml file on the http://mycontososervice.com/ site that will allow calls from http://contoso.com/. The location of the file must be located on the root of the site (http://mycontososervice.com/clientaccesspolicy.xml).
Here is a graphical representation of what is going on:
The clientaccesspolicy.xml file is located where the service is being hosted. This is a very important point. Most Silverlight developers that are starting out make a mistake in that they think the clientacesspolicy.xml is deployed onto the server where the Silverlight application is hosted. This is not true and can cause many debugging headaches. The clientacesspolicy.xml NEEDS to be deployed on the server hosting the WCF service so that Silverlight can properly consume it.
Note: For simplicity reasons, I am not adding the crossdomain.xml file which is used by Flash. Silverlight also uses this file in case the clientaccesspolicy.xml doesn't exist. This is done for obvious reasons as Flash/Flex has a bigger install base and Silverlight is simply leveraging a possibly pre-existing cross-domain file.
Example of the format of the clientaccesspolicy.xml file that grants all domains access:
Example of the format of the clientaccesspolicy.xml file that grants access ONLY to contoso.com:
Note: Notice how the only change was to add the <domain uri="http://contoso.com"/>. This is more secure and other domains will be disallowed from making service calls.
Clientaccesspolicy.xml file that only grants service access from contoso.com (other requests are not fulfilled):
One of the key aspects of a clientaccesspolicy.xml file is that it needs to be accessed on the root of the website. In our example above, the request is http://mycontososervice.com/clientaccesspolicy.xml. In order to achieve this on IIS, we would simply place the clientaccesspolicy.xml file on the root of our website (default IIS: c:\inetpub\wwwroot folder). If you want to grant multiple domains access, an admin simply can modify the clientaccesspolicy.xml file.
As mentioned above, Flash has an equivalent cross-domain configuration file to Silverlight called the crossdomain.xml file. This file has a different format; however, it serves the same purpose as the Silverlight clientaccesspolicy.xml file. Let's take look at how some of the largest companies based on services use this file. You can try this yourself by using any browser.
Examples of Enterprise cross-domain configurations:
Example of the Amazon crossdomain.xml file (http://www.amazon.com/crossdomain.xml) :
Example of the MySpace crossdomain.xml file (http://www.myspace.com/crossdomain.xml):
Some notes to take away from the two examples above:
As you can see, maintaining these files can get quite complex very quickly in more advanced scenarios. These files need to be accurate and improperly formatted xml config files can cause the validation of the configuration to be invalidated.
Problems with maintaining the clientaccesspolicy.xml file manually
Maintaing the clientaccesspolicy.xml file manually on a single or even a couple of servers is not a problem. However, maintaining complex properly validated clientaccesspolicy.xml files on multiple servers or domains can be quite challenging. One single fat finger and the file can invalidate all service calls. Improperly adding or not removing a domain can cause a serious security violation.
Scenarios where manually maintaining the clientaccesspolicy.xml file manually can be an issue:
Obviously some of these challenges can be mitigated with other security measures and designs. However, let's assume that in your scenario you have a properly working architecture/deployment and the clientaccesspolicy.xml file is becoming a maintenance nightmare. What can you do?
To overcome complex cross-domain scenarios by using some of the more advanced features of ASP.NET, we can mitigate some of the manual work that comes with creating cross-domain policy files. HttpHandlers are one way to solve some of the problems I listed above.
Httphandlers are a pretty powerful tool for ASP.NET applications that extend ISAPI extensions. There are many uses for Httphandlers and one of them is to map certain web requests to specific handler functionality. (I am not going to go over handlers in detail. If you need more information, try this link: http://www.15seconds.com/issue/020417.htm). We can create an HttpHandler that will see a request for a clientaccesspolicy.xml file. Instead of manually copying the file off of the root server, we can generate the file dynamically.
We are going to create a few sample handlers and add functionality to each one.
Basic Clientaccesspolicy Handler Part 1 - HttpHandler basics
You should have something like this now: (If not, simply just copy and paste the code from below)
Basic Clientaccesspolicy Handler Part 2 - HttpHandler adding some code
XDocument clientaccessPolicyDoc = XDocument.Parse(
@"<?xml version=""1.0"" encoding=""utf-8""?>
<access-policy>
<cross-domain-access>
<policy>
<allow-from http-request-headers=""*"">
<domain uri=""*""/>
</allow-from>
<grant-to>
<resource path=""/"" include-subpaths=""true""/>
</grant-to>
</policy>
</cross-domain-access>
</access-policy>");
context.Response.Write(clientaccessPolicyDoc.ToString());
Your class file should now look like the following:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Xml.Linq;
namespace SilverlightCrossDomainHandler
{
public class BasicClientaccesspolicyHandler : IHttpHandler
{
#region IHttpHandler Members
public bool IsReusable
{
get { return true; }
}
public void ProcessRequest(HttpContext context)
{
XDocument clientaccessPolicyDoc = XDocument.Parse(
@"<?xml version=""1.0"" encoding=""utf-8""?>
<access-policy>
<cross-domain-access>
<policy>
<allow-from http-request-headers=""*"">
<domain uri=""*""/>
</allow-from>
<grant-to>
<resource path=""/"" include-subpaths=""true""/>
</grant-to>
</policy>
</cross-domain-access>
</access-policy>");
context.Response.Write(clientaccessPolicyDoc.ToString());
}
#endregion
}
}
This will go over deploying the HttpHandler solution we created above into IIS 7.0. I wanted to provide some basic instructions on deploying handlers as it can be tricky, making this article a complete resource. However, this article is not about deployment so I will cover only IIS 7.0. Why IIS 7.0 and not 6.0? Simply because I think that most advanced developers should be taking advantage of IIS 7.0 features and some of the new WCF 4.0 bits will only work in IIS 7.0. If you haven't converted to developing on either Vista or Windows 2008 now is a good time to do so.
This is one way we can deploy the HttpHandler on our server. I like this solution as it is a global way to add the handlers to the entire web server and it is simpler to follow. There are several different ways to do this. Another good solution would be to deploy the handlers with a Silverlight web project. This way the clientaccesspolicy.xml handler is only enabled when a Silverlight application is deployed.
Testing managed HttpHandlers (inside the browser)
To test our deployment simply point your browser to http://localhost/clientaccesspolicy.xml. Of course, you want to make sure that you actually do not have a clientaccesspolicy.xml file on the root of IIS. If you put the URL into the browser and click OK, you will simply get a blank page (as this is not an HTML/ASPX/RSS etc request that has a visual reponse). You can either use Fiddler or Web Development Helper. To test using the Web Development Helper (for those that use Fiddler, you know how to do this already):
Note on the screen shot that Enable Logging is checked. We received a response from the request and the Response Contect is well formed for the clientaccesspolicy.xml and it is ready to serve us:
The fun doesn't stop here :) Since we deployed the handler to handle ANY request anywhere for clientaccesspolicy.xml (which you may or may not want to do). All requests for subdomains work fine as well and are handled by the very same handler we installed. In my test case I created a sub domain and profiled and it works fine:
TroubleShooting
If you do not have the proper IIS ASP.NET and Extensibility add-ons (ISAPI) turned on, you might receive this error: (Simply go back to Add/Remove programs and add the ASP.NET and Extensibility features for IIS). Furthermore, ensure that ASP.NET is properly registered on your site.
This article introduced you to some of the basics in managing a clientaccesspolicy.xml file for the Enterprise. We looked at other cross domain files how they are published in Enterprise scenarios and how some scenarios could warrant a more dyanmic configuration file. One way to solve the complexity of dynamic cross-domain configurations is to use HttpHandlers to create the configuration for us. In part 1 of the series we created a simple HttpHandler that returned a well formed file. In part 2 of the series, we will create a dynamic clientacesspolicy.xml file from a database store that will properly create the file in a more complex scenario.
SilverlightCrossDomainHandler.zip (18.51 kb)
DotNetKicks.com said:
Trackback from DotNetKicks.com
Silverlight clientaccesspolicy.xml files for the Enterprise (Part 1/2)
Community Blogs said:
Trackback from Community Blogs
Silverlight Cream for November 19, 2008 -- #432
# 十一月 19 2008, 08:19
from :http://silverlighthack.com/post/2008/11/08/Silverlight-clientaccesspolicyxml-files-for-the-Enterprise-(Part-1-of-2).aspx