ドメイン間アクセスの制限の緩和
Silverlightで通信を行う場合に、必ず問題となるのがクロスドメインの問題です。
Silverlightアプリケーションで、そのアプリケーションがホストされているドメイン以外と通信を行う場合、通信先のドメインに配置された、ドメイン間ポリシーファイルのポリシーにしたがって通信が制約されます。
これは、WebサイトなどにホストされたSilverlightアプリケーションが、DDoS攻撃などに利用されないために用意されているセキュリティーのための機能です。
詳しくは、次の記事を参照してください。Silverlightとサーバーサービスの連携
Silverlightでは、信頼されたアプリケーションで構成されている場合に限り、ドメイン間アクセスの制限から解放されます。例えば、System.Net.WebClientクラスを使ったHTTP通信であれば、ドメイン間ポリシーファイルの存在の有無に関係なく通信できます。
リスト2 は、ドメイン間ポリシーファイルを配置していない、筆者のブログのRSSを取得するコードです。通常のブラウザー外実行の場合、セキュリティ例外が表示され、信頼されたアプリケーションであれば取得したRSSのXMLが表示されるのを確認できます。
var client = new WebClient(); client.DownloadStringCompleted += (_s, _e) => { if (_e.Error != null) { MessageBox.Show(_e.Error.ToString()); return; } MessageBox.Show(_e.Result); }; client.DownloadStringAsync(new Uri("http://karuakun.wordpress.com/feed/"), null);
System.Net.Socketクラスを利用したクロスドメインのサンプルも見ておきましょう。通常、System.Net.Socketクラスを使った通信を行う場合、MSDNのネットワークセキュリティのアクセス制限にあるように、ポリシーファイルを配信するようなサービスを別途作るなど、多少面倒な手順が必要になります。
リスト9 は、画面のFTP接続ボタンがクリックされたタイミングで、ローカルコンピューターで稼働中のFTPサーバーに接続して、切断する簡単なサンプルです。ここでは、サンプルの詳細な解説は行いません。
private void ConnectFtpServer(object sender, RoutedEventArgs e) { var host = new DnsEndPoint("localhost", 21); var ftpSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); var args = new SocketAsyncEventArgs() { RemoteEndPoint = host, UserToken = ftpSocket, }; args.Completed += args_Completed; ftpSocket.ConnectAsync(args); } void args_Completed(object sender, SocketAsyncEventArgs e) { // 通常のアクセスの場合はAccessDeniedになる。 if (e.SocketError != SocketError.Success) Deployment.Current.Dispatcher.BeginInvoke( () => { MessageBox.Show("失敗"); }); else Deployment.Current.Dispatcher.BeginInvoke( () => { MessageBox.Show("成功"); }); e.ConnectSocket.Close(); }
Socketクラスを利用したドメイン間通信では、通信が開始されると、まず最初に接続先コンピューターの943番ポートでホストされているドメイン間ポリシーファイルを取得しようとします。今回の例では、localhost:943にドメイン間ポリシーファイル用のサービスは提供されていません。このため、通常のSilverlightからの利用の場合は、e.SocketErrorがAccessDeniedになり、接続に失敗しますが、信頼されたアプリケーションで実行する場合は、ドメイン間ポリシーファイルを利用しないため、問題なくFTPサーバーに接続できます。
MSDNのネットワーク セキュリティのアクセス制限 (Silverlight)にある通り、Silverlight4でSocketクラスを使った通信を行う場合、943番のポートでポリシーファイル用のサービスを作成する以外にも、80番ポートを利用したポリシーファイルの配布を検討することができます。