Silverlight 支持使用 http/httpS (System.Net.WebClIEnt 等) 和 Socket (System.Net.sockets) 两种方式访问远程服务器,但基于安全原因,对这些网络访问制定了严格的安全策略。
1. http/httpS 访问策略
(1) 始终允许同域调用。同域是指调用必须使用同一子域、协议和端口,这是出于安全原因以及防止跨域伪造。
(2) Silverlight 支持访问包含跨域策略文件的网站服务。跨域访问时,Silverlight Application 首先在目标 Web 服务的根路径查找 Silverlight 跨域策略文件 (clIEntaccesspolicy.xml)。如果没找到(404 Not Found)或发生其他错误,将继续在根路径处查找 Flash 跨域策略文件 (crossdomain.xml)。
clIEntaccesspolicy.xml <?xml version="1.0" enCoding="utf-8"?><access-policy> <cross-domain-access> <policy> <allow-from> <domain uri="*"/> </allow-from> <grant-to> <resource path="/" include-subpaths="true"/> </grant-to> </policy> </cross-domain-access></access-policy>
(3) 所有通信都是异步的。
(4) 仅支持 GET 和 POST 谓词。
(5) 支持大多数标准请求标头和所有自定义请求标头(必须是跨域策略文件中允许的标头)。
<?xml version="1.0" enCoding="utf-8"?><access-policy> <cross-domain-access> <policy > <allow-from http-request-headers="SOAPAction,x-custom-header"> <domain uri="*"/> </allow-from> <grant-to> <resource path="/services/" include-subpaths="true"/> </grant-to> </policy> </cross-domain-access></access-policy>
(6) 只有 "200 OK" 和 "404 Not Found" 状态代码可用。
我们尝试用 WebClIEnt 访问一个跨域网站。
private voID button_Click(object sender,RoutedEventArgs e){ var clIEnt = new WebClIEnt(); clIEnt.DownloadStringCompleted += (s,ex) => { this.TextBlock1.Text = ex.Error != null ? ex.Error.ToString() : ex.Result; }; clIEnt.DownloadStringAsync(new Uri("http://localhost:8081/",UriKind.absolute));}
当目标网站没有提供策略文件时,你会看到如下的错误信息。
在其根路径放置好 clIEntaccesspolicy.xml 后,访问正常。
2. Sockets 访问策略
创建一个供 Silverlight Application 连接的 Socket Server (非同域网站),必须符合以下安全策略。
(1) 监听 943 端口,为 Silverlight Application 提供策略文件(clIEntaccesspolicy.xml)。
(2) Socket Server 的服务端口范围必须在 4502 - 4534 之间。这是 Silverlight Application Socket 连接所允许使用的端口范围,否则连接失败。
我们写一个简单的 Time Server 作为演示。
Server CUI class Program{ static voID Main(string[] args) { AccesspolicyServer(); TimeServer(); Console.Writeline("Press any key to exit..."); Console.ReadKey(true); Environment.Exit(0); } /// <summary> /// 创建时间服务器线程 /// </summary> private static voID TimeServer() { new Thread(() => { // 监听 4502 端口 var server = new TcpListener(IPAddress.Parse("127.0.0.1"),4502); server.Start(); while (true) { var clIEnt = server.AcceptTcpClIEnt(); var stream = clIEnt.GetStream(); // 发送当前时间 var send = EnCoding.UTF8.GetBytes(DateTime.Now.ToString()); stream.Write(send,send.Length); clIEnt.Close(); } }).Start(); } /// <summary> /// 创建策略文件服务器线程 /// </summary> private static voID AccesspolicyServer() { new Thread(() => { // 监听 943 端口 var server = new TcpListener(IPAddress.Parse("127.0.0.1"),943); server.Start(); while (true) { var clIEnt = server.AcceptTcpClIEnt(); var stream = clIEnt.GetStream(); // 读取客户端发送信息,如果请求字符串不匹配则断开。 var buffer = new Byte[1024]; var len = stream.Read(buffer,buffer.Length); var rece = EnCoding.UTF8.GetString(buffer,len); if (String.Compare(rece,"<policy-file-request/>",true) != 0) { clIEnt.Close(); break; } Console.Writeline(rece); // 发送策略文件内容 var send = EnCoding.UTF8.GetBytes(@" <?xml version=""1.0"" enCoding=""utf-8""?> <access-policy> <cross-domain-access> <policy> <allow-from> <domain uri=""*""/> </allow-from> <grant-to> <socket-resource port=""4502-4534"" protocol=""tcp"" /> </grant-to> </policy> </cross-domain-access> </access-policy>"); stream.Write(send,send.Length); clIEnt.Close(); } }).Start(); }}ClIEnt Silverlight XAP private voID button_Click(object sender,RoutedEventArgs e){ // 创建 Socket var clIEnt = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp); // 创建等待句柄 var wait = new ManualresetEvent(true); // 创建连接参数 var args = new socketasynceventargs(); args.RemoteEndPoint = new DnsEndPoint("127.0.0.1",4502); // 订阅处理事件 args.Completed += (s,ex) => { if (ex.Lastoperation == SocketAsyncoperation.Connect) { // 连接完成,则设置缓冲区 var buffer = new byte[1024]; ex.SetBuffer(buffer,buffer.Length); // 接收服务器数据 clIEnt.ReceiveAsync(ex); } else if (ex.Lastoperation == SocketAsyncoperation.Receive) { // 如果接收信息正确,则显示服务器发送内容,否则显示错误信息。 if (ex.socketError == SocketError.Success) { this.dispatcher.BeginInvoke(() => { this.TextBlock1.Text = EnCoding.UTF8.GetString(ex.Buffer,ex.BytesTransferred); }); } else { this.dispatcher.BeginInvoke(() => { this.TextBlock1.Text = ex.socketError.ToString(); }); } wait.Set(); } }; // 连接服务器 clIEnt.ConnectAsync(args); // 等待处理结束 wait.WaitOne();}
如果不启动服务器策略文件服务,或者端口不是 943,你会在客户端获得一个 AccessDenIEd 错误。
当然,如果服务器监听端口不再允许范围(4502 - 4534)内,同样也会触发这样一个错误。
【reprinted from http://www.rainsts.net/】
总结以上是内存溢出为你收集整理的Silverlight 中的通信安全访问策略全部内容,希望文章能够帮你解决Silverlight 中的通信安全访问策略所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)