Silverlight 运行时支持若干将网络应用程序与远程主机进行连接的主要方法:
-
System.Net 命名空间中的 WebClient 和 HTTP 类 - 这些类使用 HTTP 或 HTTPS 协议来进行网络通信。这些类使用如下所述的安全策略系统和策略文件。
-
System.Net.Sockets 命名空间中的套接字类 - 这些类提供一个低级别的套接字接口,该接口可用于更常规的使用单播的网络通信。这些类使用如下所述的安全策略系统和策略文件。
-
System.Net.Sockets 命名空间中的 UdpAnySourceMulticastClient 和 UdpSingleSourceMulticastClient 类 -- 这些类为 UDP 多路广播客户端提供支持。Silverlight 版本 4 中添加了这些类。这些类使用不同的安全机制(多路广播安全策略协议),而不是如下所述的安全策略系统和策略文件。有关更多信息,请参见使用多播。
在所有情况下,都需要提供安全性并防止 Silverlight 应用程序启动未经授权的连接。要缓解的潜在网络威胁包括:
-
拒绝服务 (DoS) 攻击 – 大量的远程主机用于攻击一个目标站点,以使目标无法为有效的请求提供服务。
-
DNS 重新绑定攻击 – 使用 DNS 以强制远程主机将受信任的主机名(源站点)重新绑定到受害者的 IP 地址,这样就允许访问除源站点之外的其他主机。
-
反向隧道攻击 – 将远程客户端的外发连接用作客户端专用网络的后退隧道。
Silverlight 版本 2 和更高版本中纳入的安全策略系统旨在防止这些网络威胁。此外,此策略系统还向管理员提供更多的控制权,以控制允许远程客户端连接哪些资源。
以前对于支持网络的插件的设计将连接性限制到主机或源站点。这意味着,Web 应用程序只能向后与其部署服务器通信,因此,网络应用程序可以连接到从中下载它们的主机。
Silverlight 2 和更高版本包括对跨域连接的支持,这使得应用程序可以访问并非源站点的其他位置中的资源。这是一个重要的功能,它使 Silverlight 应用程序可以使用 Web 上的现有服务。 Silverlight 运行时中的安全策略系统要求必须先从目标域下载一个策略文件,之后才允许网络连接访问该目标域下的网络资源。此安全策略系统影响针对 System.Net 命名空间中的 WebClient 和 HTTP 类的跨域网络访问。WebClient 和 HTTP 类的针对源站点或源主机的网络连接不要求安全策略。
请注意,从 Silverlight 应用程序对网络资源的跨域访问也可能会受到域、本地 Intranet 和本地计算机上已设定的其他安全性和防火墙策略的限制。例如,其他安全性和防火墙策略可能会限制对 http://contoso 形式的 URI 的访问,而允许对具有全限定域名的 http://www.contoso.com 的类似 URI 的访问。
对于使用 System.Net.Sockets 的网络连接,Silverlight 中的安全策略系统将同时影响源站点和跨域网络访问。使用套接字的所有连接都需要安全策略,即使当连接回到源站点时也是如此。
Silverlight 中的安全策略系统可以防止启动未经授权的连接,以及防止针对本地计算机或本地网络上的其他设备的可能网络攻击威胁;但同时,这些策略检查也为部署合法 Silverlight 应用程序设置了屏障。为了方便编写和部署使用 System.Net.Sockets 进行通信的 Silverlight 应用程序,Silverlight 版本 4 为浏览器外受信任的应用程序引入了较为宽松的限制。使用此功能,经过用户授权的浏览器外 Silverlight 应用程序运行在扩展的沙盒中,而不必接受对 System.Net.Sockets 的安全策略检查。有关浏览器外支持和受信任的应用程序的一般信息,请参见浏览器外支持主题和受信任的应用程序主题。
本节中的内容提供有关如何在 Silverlight 4 中使用安全策略系统的详细信息,并介绍所支持的策略文件格式。
Silverlight 支持两个类型的安全策略文件:
-
Flash 策略文件 - 由 Adobe Flash 使用的现有 crossdomain.xml 策略文件。此策略文件只可由 System.Net 命名空间中的 WebClient 和 HTTP 类使用。Flash 策略文件必须允许访问由 Silverlight 运行时使用的所有域。
-
Silverlight 策略文件 - 既可由 System.Net 命名空间中的 WebClient 和 HTTP 类使用,也可由 System.Net.Sockets 命名空间中的套接字类使用的 Silverlight 策略文件。此策略文件与 Flash 策略文件具有不同的格式。
在允许连接某个网络资源之前,Silverlight 运行时将尝试从承载该网络资源的域下载安全策略文件。可以通过两种不同方法下载安全策略,具体取决于连接请求是来自 WebClient 或 HTTP 类,还是来自套接字。
如果连接请求是从 WebClient 或 HTTP 类到某个跨域站点的,则 Silverlight 运行时将使用 HTTP 协议尝试下载安全策略文件���Silverlight 运行时首先尝试使用 HTTP 协议下载所请求目标域的根目录下名为"clientaccesspolicy.xml"的 Silverlight 策略文件。
如果"clientaccesspolicy.xml"找不到(Web 请求返回 404 状态代码)、返回意外的 mime 类型、不是有效的 XML 或者具有无效的根节点,则 Silverlight 运行时将使用 HTTP 协议针对所请求目标域的根目录下名为"crossdomain.xml"的 Flash 策略文件发出一个请求。
不允许针对该策略文件的 HTTP 重定向。针对某一策略文件的重定向将导致拒绝访问 SecurityException。
如果返回一个"clientaccesspolicy.xml"文件,但包含上述错误之外的其他错误,则不允许对该域的进一步的跨域请求。
如果返回了一个有效的"clientaccesspolicy.xml"文件,该文件将用作 Silverlight 应用程序的其余客户端会话的该跨域请求的策略文件,并且将用于确定对该域的所有后续跨域请求的有效性。
Flash 策略文件必须允许连接到所有域,以便它可供 Silverlight WebClient 和 HTTP 类使用。
如果返回 Silverlight 策略文件(即使在分析该文件时出现错误),则在 Silverlight 应用程序的整个会话期间,此文件将用作该跨域请求以及针对该服务器的所有后续请求的策略文件。 如果找不到 Silverlight 策略文件,则 Silverlight 运行时尝试使用 HTTP 协议下载所请求目标域的根目录下名为"crossdomain.xml"的 Flash 策略。Flash 策略文件必须允许连接到所有域,以便它可供 Silverlight WebClient 和 HTTP 类使用。
在 Silverlight 版本 3 中,对于使用 System.Net.Sockets 连接到站点(跨域或源站点)的连接请求,Silverlight 运行时将尝试使用 TCP 打开到目标站点上某个已知端口(端口 943)的连接。如果可以建立 TCP 连接,Silverlight 运行时会将特殊字符串 <policy-file-request/> 发送到服务器以请求 Silverlight 套接字策略文件。然后,Silverlight 运行时等待从包含 Silverlight 策略文件的目标网站接收答复。如果返回此 Silverlight 套接字策略文件(即使在分析该文件时出现错误),则在 Silverlight 应用程序的整个会话期间,此文件将用作该套接字请求以及针对该目标站点的所有后续请求的策略文件。
如果分析所检索的策略文件时获得成功并策略文件授予了权限,则最终会建立到目标主机的连接。如果所检索的策略文件无效且无法正确地进行分析,Silverlight 运行时将拒绝到网络资源的连接,并且任何连接请求都将失败。如果找不到任何策略文件,Silverlight 运行时将拒绝到网络资源的连接,并且任何连接请求都将失败。
在 Silverlight 版本 4 中,对于使用 System.Net.Sockets 的连接请求,应用程序可以选择在 TCP 端口 80 上通过 HTTP 协议检索策略文件,而不是在端口 943 上通过自定义 TCP 协议来检索。这样,已在运行 HTTP 服务的 HTTP 服务器能够对来自 Silverlight 应用程序的套接字连接进行授权,而不必在计算机上部署新的 TCP 服务,再通过端口 943 的防火墙打开某个端口。将通过 HTTP 检索套接字策略文件,并且该文件用作已解析的 IP 地址的主机,其中建立了目标套接字连接。这样,目标就会有计算机资源(如套接字)所需的相应权威性计算机范围的策略。相比较而言,System.Net 命名空间中的 WebClient 和 HTTP 类所使用的策略文件将从作为 HTTP 请求的目标的主机域中检索。HTTP 协议允许通过主机标头在每个域的基础之上分离资源。
若要使用 HTTP 检索套接字策略文件,应用程序应在传递给 Socket.ConnectAsync 方法的 System.Net.Sockets.SocketAsyncEventArgs 实例上将SocketAsyncEventArgs.SocketClientAccessPolicyProtocol 属性设置为 Http。
若要使用 TCP 和端口 943 检索套接字策略文件,应用程序应在传递给 Socket.ConnectAsync 方法的 System.Net.Sockets.SocketAsyncEventArgs 实例上将 SocketAsyncEventArgs.SocketClientAccessPolicyProtocol 属性设置为 Tcp。
有关使用套接字类的一个附加限制是:允许网络应用程序连接的目标端口范围必须在范围 4502-4534 内。这些是使用套接字从 Silverlight 应用程序进行连接所允许的仅有目标端口。如果目标端口不在此端口范围内,则尝试连接时将失败。如果需要支持特定的现有应用程序协议,则目标服务器可以从该受限范围内的某个端口接收连接,并将其重定向到其他端口(例如,某个已知端口)。
若要部署策略文件以供来自 WebClient 和 HTTP 类的连接使用,系统管理员需要为每个 IP 地址(此类 IP 地址提供策略文件定义并使 Silverlight 或 Flash 策略文件可通过 HTTP 获得)配置 Web 服务。
若要在服务器上为 Silverlight 版本 3 中的套接字部署套接字策略文件,系统管理员需要在端口 943 上为要提供策略文件定义的每个 IP 地址配置一个单独的身份验证服务。
若要在服务器上为 Silverlight 版本 4 中的套接字部署策略文件,系统管理员可以选择在端口 943 上使用上述方法,或使用 HTTP 端口 80。若使用 HTTP,系统管理员需要为每个 IP 地址(此类 IP 地址提供策略文件定义并使 Silverlight 策略文件可通过 HTTP 获得)配置 Web 服务。 套接字策略文件必须存储在某个 Web 服务器根目录下的“clientaccesspolicy.xml”文件中,该 Web 服务器响应目标连接请求的已解析 IP 地址。相比较而言,System.Net 命名空间中的 WebClient 和 HTTP 类所使用的策略文件将从 Web 服务器检索,而该 Web 服务器响应作为 HTTP 请求的目标的域。如果 Web 服务器配置为仅承载单个域并且还响应对于套接字连接的服务器 IP 地址的请求,则套接字策略部分可以与用于 WebClient 和 HTTP 类的 Silverlight 策略文件结合(如果使用了一个这种文件)。
Silverlight 版本 4 运行时为作为具有提升信任的浏览器外应用程序运行的网络应用程序提供宽松的安全策略检查。使用此功能,可以在浏览器外 Silverlight 应用程序的清单中将该应用程序配置为需要以提升信任权限运行的受信任应用程序。用户在尝试安装受信任应用程序时将收到警告,此时必须在用户同意后才能安装。如果用户同意,Silverlight 受信任应用程序将在扩展的沙盒内运行,这允许其访问网络和本地资源;而出于安全原因,明确拒绝普通的 Silverlight 应用程序进行上述访问。
在 Silverlight 版本 4 中,受信任应用程序被授权使用 WebClient 和 System.Net 命名空间中的 HTTP 类,而不必接受策略检查。 例如,从使用 HTTP 协议的某个域安装的应用程序可以访问使用 HTTPS 协议的跨域站点上的媒体文件。
在 Silverlight 版本 4 中,受信任应用程序还有权使用 System.Net.Sockets 命名空间中的网络类,包括新的 UdpAnySourceMulticastClient 和 UdpSingleSourceMulticastClient 类,而不必接受策略检查。受信任应用程序无需跨域策略文件即能创建与任意主机上的任意端口的 TCP 连接。目标端口不再需要介于 4502-4534 范围之内。同样,使用 UdpAnySourceMulticastClient 和 UdpSingleSourceMulticastClient 类的受信任应用程序能够加入端口号大于等于 1024 的任意端口上的任意多路广播组,而不需要策略响应方对该连接授权。无需更多方法调用即可利用这些更改。在浏览器外应用程序作为具有提升信任的受信任应用程序运行时,现有方法不需要策略检查。
在 Silverlight 版本 4 上,浏览器内 Silverlight 应用程序或未提升信任的浏览器外 Silverlight 应用程序必须满足所有安全策略检查要求。如果安全策略检查失败,在 SocketException.SocketErrorCode 属性设置为 SocketError.AccessDenied 时,未提升信任的 Silverlight 应用程序仍会继续引发 System.Net.Sockets.SocketException。
下面的内容使用 DTD 介绍 Silverlight 策略文件格式。
<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- A DTD for the Silverlight Policy File -->
<!ELEMENT access-policy (cross-domain-access)>
<!ELEMENT cross-domain-access (policy+)>
<!ELEMENT policy (allow-from)>
<!ELEMENT policy (grant-to)>
<!ELEMENT allow-from (domain+)>
<!ATTLIST allow-from http-request-headers CDATA>
<!ELEMENT domain EMPTY >
<!ATTLIST domain uri CDATA #REQUIRED>
<!ELEMENT allow-from http-methods CDATA>
<!ELEMENT grant-to (resource+)>
<!ELEMENT grant-to (socket-resource+)>
<!ELEMENT grant-to EMPTY>
<!ATTLIST resource path CDATA #REQUIRED>
<!ATTLIST resource include-subpaths (true|false) "false">
<!ATTLIST socket-resource port CDATA #REQUIRED protocol #REQUIRED>
<!-- End of file. --><!-- End of file. -->
下表描述可能的 ELEMENT 条目。
|
元素 |
子项属于 |
必需 |
允许多个 |
说明 |
|---|---|---|---|---|
|
access-policy |
不可用(根) |
是 |
否 |
Silverlight 策略文件的根元素。 |
|
cross-domain-access |
access-policy |
是 |
否 |
为站点定义所有跨域策略。 |
|
policy |
cross-domain-access |
是 |
是 |
为来自特定的一个或一组域的请求定义跨域策略。 可以在同一个文件中定义多个策略。 |
|
allow-from |
policy |
是 |
否 |
定义受此策略影响的所有域。定义被允许访问特定策略中的资源的站点。 通过对特定策略使用 allow-from 元素,您可以针对所有未列出的域隐式拒绝访问。 如果 allow-from 为空,则策略文件不授予针对任何站点的访问权限。 |
|
domain |
allow-from- 或 - allow-from http-methods |
是 |
是 |
定义受此策略影响的域(或特定的 Silverlight 应用程序)。 |
|
grant-to |
policy |
是 |
否 |
定义受此策略影响的服务器的所有资源。 |
|
resource |
grant-to |
是(对于 WebClient 和 HTTP 类) |
是 |
定义在特定策略中可以访问的资源。 此元素仅适用于使用 WebClient 和 HTTP 类的连接请求。 |
|
socket-resource |
grant-to |
是(对于套接字) |
是 |
定义在特定策略中可以访问的套接字资源。 此元素仅适用于使用套接字的连接请求。 |
下表描述某个 ELEMENT 允许的可能 ATTRIBUTE 条目。
|
元素 |
属性 |
必需 |
默认值 |
说明 |
|---|---|---|---|---|
|
allow-from |
http-request-headers |
否 |
不允许标题,但 Content-Type 标题除外,后者始终是允许的。 |
一个区分大小写、以逗号分隔的列表,其中包含在域属性中指定的域所允许的标题。根据 RFC822,有效字符为 ASCII 33-41、42-57 和 59-126。这包括所有可打印的非空格 ASCII 字符(但冒号除外,它结束标题名称)和星号(用作通配符)。 通配符可用于指定所有标题,也可在单个标题名称中用作后缀以允许以字符串值开头、后接通配符的所有标题。单独使用"*"被解释为可以发送在正常情况下使用 HttpWebRequest 类所允许的所有请求标题。 某些公共标题被视为受限制,它们或者直接公开(如 Content-Type),或者受到系统保护,不能设置或更改。有关受限制标题的更多信息,请参见 WebHeaderCollection。 如果缺失此属性,则不允许发送 Content-Type 标题以外的任何标题。 |
|
allow from |
http-methods |
否 |
客户端 HTTP 处理程序仅允许 GET 和 POST 方法。 |
定义客户端 HTTP 处理程序是否允许使用 GET 和 POST 以外的自定义请求方法。只有在针对 URI 的 HTTP 处理程序改为使用客户端 HTTP 处理程序时,此策略才适用。默认的浏览器 HTTP 处理程序仅允许使用 GET 和 POST 请求方法。此策略元素允许的请求方法的唯一可能的值是通配符"*"。 |
|
domain |
uri |
是 |
不可用 |
列出允许的域和可以访问此策略中所授予路径的特定 Silverlight 应用程序。uri 指定允许连接源自的方案和域。可以指定方案和端口。 接受以下三种类型的通配符: 1.单独使用的"*"通配符被解释为接受来自在任何域上承载的相同方案的应用程序的所有连接。 2."http://*"文本通配符选项被解释为接受来自任何域的 HTTP 方案的应用程序的所有连接。 3.子域通配符选项表示为允许的方案后跟“*”字符以及“.”字符,再后跟主机名的剩余部分。该通配符用作主机名的第一个部分。这被视为子域通配符。"http://*.contoso.com"的属性值只允许 HTTP 用于该方案,并且接受来自在"contoso.com"的任何子域上承载的 Silverlight 应用程序的连接。 |
|
resource |
path |
是(对于 WebClient 和 HTTP 类) |
不可用 |
此属性是相对于域的根目录的 URI。它指向可表示 Web 服务或文件的特定路径。 路径可能包含通配符或"统一资源标识符 (URI):泛型语法"无法识别的字符:http://ietf.org/rfc/rfc3986 此元素和属性仅用于来自 WebClient 和 HTTP 类的请求。 |
|
resource |
include-subpaths |
否 |
False |
指定是否应包括关联路径的子路径。 如果值为 true,则允许与由路径属性指定的确切路径相匹配的路径,或者与由路径属性指定的路径和任何追加的子路径相匹配的路径。 如果值为 false,则只允许与由路径属性指定的确切路径相匹配。如果省略此属性,则默认值为 false。 此元素和属性仅用于来自 WebClient 和 HTTP 类的请求。 |
|
socket-resource |
port |
是 |
不可用 |
指定使用套接字的应用程序可以连接的端口或端口范围。 此元素和属性仅用于来自套接字类的请求。 |
|
socket-resource |
protocol |
是 |
不可用 |
指定使用套接字的应用程序可以连接的协议。 当前唯一支持的协议是 TCP。 此元素和属性仅用于来自套接字类的请求。 |
域元素的 uri 属性指的是域以及允许访问该策略文件内的 <grant-to> 元素标记指定的路径的特定 Silverlight 应用程序。包括的域必须与请求的域完全匹配。例如,域 uri="http://contoso.com" 只允许从 http://contoso.com 访问,而不允许从 http://web.contoso.com 访问。
允许以下三种不同类型的通配符:
-
单独的"*"通配符。此选项用于允许访问同一方案的所有域。HTTP 服务将允许所有 HTTP 调用方。HTTPS 服务将允许所有 HTTPS 调用方。
-
"http://*"文本通配符。此选项显式允许所有 HTTP 调用方,即使该调用方是 HTTPS 服务也允许。
-
子域通配符。此选项在路径的第一部分使用一个通配符(例如"http://*.contoso.com"),从而允许指定的域的所有子域。因此,就这个示例而言,将允许 http://web.contoso.com 和 http://mail.contoso.com。请注意,不允许该通配符没有作为前缀出现(例如 http://web.*.com)的 uri 路径。
Silverlight 策略文件允许使用跨域策略文件连接到 HTTPS 服务。 当在策略中提供针对某一域元素的显式 allow-from 属性时,该域包括方案信息。下面是一个示例:
<allow-from>
<domain uri="https://contoso.com">
</allow-from>).
上面的策略将只允许使用 HTTPS 方案从 https://contoso.com 进行的连接。
单独"*"通配符的 Silverlight 策略文件的通配符行为依赖于要访问的服务类型:
|
|
HTTP 服务 <domain uri=”*”/> |
HTTPS 服务 <domain uri=”*”/> |
|---|---|---|
|
HTTP 承载的 Silverlight 应用程序 |
允许 |
拒绝 |
|
HTTPS 承载的 Silverlight 应用程序 |
允许 |
允许 |
此通配符行为允许在 HTTP 和 HTTPS 上承载的所有 Silverlight 应用程序连接到 HTTP 服务。它只允许在 HTTPS 上承载的 Silverlight 应用程序连接到 HTTPS 服务。
“http://*”文本通配符的 Silverlight 策略文件的通配符行为依赖于要访问的服务类型:
|
|
HTTP 服务 <domain uri=”http://*”/> |
HTTPS 服务 <domain uri=”http://*”/> |
|---|---|---|
|
HTTP 承载的 Silverlight 应用程序 |
允许 |
允许 |
|
HTTPS 承载的 Silverlight 应用程序 |
拒绝 |
拒绝 |
此 "http://*" 文本通配符行为允许在 HTTP 上承载的所有 Silverlight 应用程序连接到 HTTP 或 HTTPS 服务。
“https://*”文本通配符的 Silverlight 策略文件的通配符行为依赖于要访问的服务类型:
|
|
HTTP 服务 <domain uri=”https://*”/> |
HTTPS 服务 <domain uri=”https://*”/> |
|---|---|---|
|
HTTP 承载的 Silverlight 应用程序 |
拒绝 |
拒绝 |
|
HTTPS 承载的 Silverlight 应用程序 |
允许 |
允许
|
此 "http://*" 文本通配符行为允许在 HTTP 上承载的所有 Silverlight 应用程序连接到 HTTP 或 HTTPS 服务。
如果某一 HTTPS 服务想要允许来自 HTTP 和 HTTPS 的所有连接,则在 Silverlight 版本 3 上有两种方法可实现此目的。一种方法是策略文件必须为单独的"*"通配符和 "http://*" 文本通配符都包括域 uri 条目。 下面是一个示例:
<allow-from>
<domain uri="*">
<domain uri="http://*">
</allow-from>).
第二种方法是策略文件必须为独立的 "http://*" 文本通配符和 "https://*" 文本通配符都包括域 uri 条目。下面是一个示例:
<allow-from>
<domain uri="http://*">
<domain uri="https://*">
</allow-from>).
您隐式拒绝未在 Silverlight 策略文件的 <domain> 元素标记中列出的所有域的访问。
每个域都必须采用以下 BNF 格式:
-
domain = "http:"|"https:" authority
-
authority = host [ ":" port ]
-
host = ALPHA *( ALPHA / DIGIT / "+" / "-" / ".")
-
port = *DIGIT
每个 Silverlight 应用程序 uri 都是绝对 uri,没有针对 .html、.xaml 或 .xap 文件的查询或片断。
在为某一 URI 指定了客户端 HTTP 处理程序后,Silverlight 策略文件允许 GET 和 POST 以外的其他自定义方法。默认浏览器 HTTP 处理程序仅允许使用 GET 和 POST 请求。在指定某一 allow-from http-methods 元素时,允许的请求方法必须指定为通配符"*"。域包括架构信息。下面是一个示例:
<allow-from http-methods="*">
<domain uri="*">
</allow-from>).
以上策略仅允许客户端 HTTP 处理程序使用 GET 和 POST 请求以外的自定义请求。为 Silverlight 版本 3 添加了 allow-from http-methods 策略元素。该策略元素不会被 Silverlight 版本 2 客户端识别。如果某一服务器需要同时支持 Silverlight 3 和 Silverlight 2 客户端,则策略文件应该包含两个策略部分,一个针对 allow-from http-methods 策略元素,另一个针对 allow-from 策略元素。下面是一个示例:
<?xml version="1.0" encoding="utf-8"?>
<access-policy>
<cross-domain-access>
<!--Enables Silverlight 3 all methods functionality-->
<policy>
<allow-from http-methods=”*">
<domain uri="*"/>
</allow-from>
<grant-to>
<resource path="/api" include-subpaths="true"/>
</grant-to>
</policy>
<!--Enables Silverlight 2 clients to continue to work normally -->
<policy>
<allow-from >
<domain uri="*"/>
</allow-from>
<grant-to>
<resource path="/api" include-subpaths="true"/>
</grant-to>
</policy>
</cross-domain-access>
</access-policy>
单个 Silverlight 策略文件可能包括用于来自 System.Net 命名空间中 WebClient 和 HTTP 类的连接请求的策略,也可能包含用于来自套接字中的连接请求的策略。
用于确定策略文件是否允许某个请求的过程如下所示:
所请求 URI 的架构是否与应用程序的源站点相同?HTTP 是否为请求的 URI 的方案并且应用程序的源站点的方案是否为 HTTPS?HTTPS 是否为请求的 URI 的方案并且应用程序的源站点的方案是否为 HTTP?如果不属于上述三种情况的任何一种,则请求没有访问权限并且不应发送。
对于每个 <policy> 元素:
-
是否允许访问应用程序的源站点?这可以在 <policy> allow-from 域属性中显式实现,或者 allow-from 属性可能具有一个将通配符用于 uri 属性的域元素(指示允许任何人访问)。请注意,如果忽略 allow-from,则默认行为是不允许任何人访问。
-
策略是否授予针对请求 URI 的访问权限?
如果以下任何条件成立,则请求将确实具有访问权限,并且应发送此请求。否则,请转到文件中的下一个 <policy>。
-
所请求的 URI 与 <resource> 标记中的域和路径完全匹配。
-
所请求的 URI 位于 <grant-to> 标记内的域和路径之下,并且 <grant-to> 标记的 include-subpaths 属性已将值设置为 true。
-
对于套接字请求,此 <policy> 的 <grant-to> 部分中 <socket-resource> 标记内的协议和端口属性为协议和端口或所允许范围 4502-4534 内的端口范围指定 tcp。
示例 1 - 一个 HTTP 服务
下面是一个示例 Silverlight 策略文件,它使用 System.Net 命名空间中的 WebClient 和 HTTP 类来跨域连接到某一 HTTP 服务。该策略文件接受来自任何域的连接。此策略文件限制请求标题,且不包括子路径。
<?xml version="1.0" encoding="utf-8"?>
<access-policy>
<cross-domain-access>
<policy>
<allow-from>
<domain uri="*"/>
</allow-from>
<grant-to>
<resource path="/api" include-subpaths="false"/>
</grant-to>
</policy>
</cross-domain-access>
</access-policy>
对于以上策略文件,可以从在任何站点上承载的 Silverlight HTTP 应用程序访问这些资源:
对于上述策略文件,无法访问这些资源:
对于以上策略文件,除了始终允许的 Content-Type 标题外,不能发送任何请求标题。
示例 2 - 一个 HTTP 服务
下面是一个示例 Silverlight 策略文件,它使用 System.Net 命名空间中的 WebClient 和 HTTP 类来跨域连接到某一 HTTP 服务。 该策略文件接受来自任何域的连接。该策略文件允许请求标题,它还指定可访问的资源并且包括这些资源的子路径。
<?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="/api" include-subpaths="true"/>
</grant-to>
</policy>
</cross-domain-access>
</access-policy>
对于以上策略文件,可以从在任何站点上承载的 Silverlight HTTP 应用程序访问这些资源:
对于上述策略文件,无法访问这些资源:
对于上述策略文件,可以发送在正常情况下使用 HttpWebRequest 类所允许的所有请求标题。
示例 3 - 一个 HTTP 服务
下面是一个示例 Silverlight 策略文件,它使用 System.Net 命名空间中的 WebClient 和 HTTP 类来跨域连接到某一 HTTP 服务。该策略文件仅接受来自指定的域和方案的连接。该策略文件指定特定的请求标题,并且指定可访问的资源。
<?xml version="1.0" encoding="utf-8"?>
<access-policy>
<cross-domain-access>
<policy>
<allow-from http-request-headers="MyHeader, X-API-*">
<domain uri="http://electronics.fabrikam.com"/>
<domain uri="http://books.fabrikam.com"/>
<domain uri="http://contoso.com:8080"/>
</allow-from>
<grant-to>
<resource path="/costcalculations"/>
</grant-to>
</policy>
</cross-domain-access>
</access-policy>
对于上述策略,允许如下所列的 Silverlight HTTP 应用程序访问 /costcalculations:
http://electronics.fabrikam.com/sample/app.xap http://books.fabrikam.com/web/sample/app.html http://contoso.com:8080/sample/app.xap
对于上述策略,不允许如下所列的 Silverlight 应用程序访问 /costcalculations:
http://electronics.fabrikam.com:8080/sample/app.xap http://electronics.fabrikam.com:8080/sample/app.xap http://bar.com/sample/app.xaml https://bar.com/sample/app.html
以下 HTTP 请求标题可发送(以及始终允许发送的 Content-Type 标题):
示例 4 - 一个 HTTPS 服务
下面是一个示例 Silverlight 策略文件,它使用 System.Net 命名空间中的 WebClient 和 HTTP 类来跨域连接到某一 HTTPS 服务。该策略文件接受来自任何域的连接。 该策略文件限制请求标题,并且指定可访问的资源。
<?xml version="1.0" encoding="utf-8"?>
<access-policy>
<cross-domain-access>
<policy>
<allow-from>
<domain uri="*"/>
</allow-from>
<grant-to>
<resource path="/costcalculations"/>
</grant-to>
</policy>
</cross-domain-access>
</access-policy>
对于以上策略文件,允许在任何站点上承载的 Silverlight HTTPS 应用程序访问 /costcalculations:
对于以上策略文件,除了始终允许的 Content-Type 标题外,不能发送任何请求标题。
对于上述策略,允许如下所列的 Silverlight 应用程序访问 /costcalculations:
https://electronics.fabrikam.com/sample/app.xap https://books.fabrikam.com/web/sample/app.html https://contoso.com:8080/app.xap
对于上述策略,不允许如下所列的 Silverlight 应用程序访问 /costcalculations:
示例 5 - 一个 HTTPS 服务
下面是一个示例 Silverlight 策略文件,它使用 System.Net 命名空间中的 WebClient 和 HTTP 类来跨域连接到某一 HTTPS 服务。此策略文件指定特定的请求标题。
<?xml version="1.0" encoding="utf-8"?>
<access-policy>
<cross-domain-access>
<policy>
<allow-from http-request-headers="MyHeader, X-API-*">
<domain uri="*"/>
<domain uri="http://*"/>
</allow-from>
<grant-to>
<resource path="/costcalculations"/>
</grant-to>
</policy>
</cross-domain-access>
</access-policy>
对于以上策略文件,允许在任何站点上承载的 Silverlight HTTP 和 HTTPS 应用程序访问 /costcalculations:
以下 HTTP 请求标题可发送(以及始终允许发送的 Content-Type 标题):
下面是使用套接字进行连接的示例 Silverlight 策略文件。
以下示例在托管代码中为套接字实现了简单的策略服务器,该服务器在端口 943 上侦听请求以检索套接字要使用的策略文件。该示例策略服务器要求当启动服务器时将策略文件的名称用作一个参数。
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
namespace PolicyServer
{
// Encapsulate and manage state for a single connection from a client
class PolicyConnection
{
private Socket m_connection;
// buffer to receive the request from the client
private byte[] m_buffer;
private int m_received;
// the policy to return to the client
private byte[] m_policy;
// the request that we're expecting from the client
private static string s_policyRequestString = "<policy-file-request/>";
public PolicyConnection(Socket client, byte[] policy)
{
m_connection = client;
m_policy = policy;
m_buffer = new byte[s_policyRequestString.Length];
m_received = 0;
try
{
// receive the request from the client
m_connection.BeginReceive(m_buffer, 0, s_policyRequestString.Length, SocketFlags.None, new AsyncCallback(OnReceive), null);
}
catch (SocketException)
{
m_connection.Close();
}
}
// Called when we receive data from the client
private void OnReceive(IAsyncResult res)
{
try
{
m_received += m_connection.EndReceive(res);
// if we haven't gotten enough for a full request yet, receive again
if (m_received < s_policyRequestString.Length)
{
m_connection.BeginReceive(m_buffer, m_received, s_policyRequestString.Length - m_received, SocketFlags.None, new AsyncCallback(OnReceive), null);
return;
}
// make sure the request is valid
string request = System.Text.Encoding.UTF8.GetString(m_buffer, 0, m_received);
if (StringComparer.InvariantCultureIgnoreCase.Compare(request, s_policyRequestString) != 0)
{
m_connection.Close();
return;
}
// send the policy
m_connection.BeginSend(m_policy, 0, m_policy.Length, SocketFlags.None, new AsyncCallback(OnSend), null);
}
catch (SocketException)
{
m_connection.Close();
}
}
// called after sending the policy to the client; close the connection.
public void OnSend(IAsyncResult res)
{
try
{
m_connection.EndSend(res);
}
finally
{
m_connection.Close();
}
}
}
// Listens for connections on port 943 and dispatches requests to a PolicyConnection
class PolicyServer
{
private Socket m_listener;
private byte[] m_policy;
// pass in the path of an XML file containing the socket policy
public PolicyServer(string policyFile)
{
// Load the policy file
FileStream policyStream = new FileStream(policyFile, FileMode.Open);
m_policy = new byte[policyStream.Length];
policyStream.Read(m_policy, 0, m_policy.Length);
policyStream.Close();
// Create the Listening Socket
m_listener = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
// Put the socket into dual mode to allow a single socket
// to accept both IPv4 and IPv6 connections
// Otherwise, server needs to listen on two sockets,
// one for IPv4 and one for IPv6
// NOTE: dual-mode sockets are supported on Vista and later
m_listener.SetSocketOption(SocketOptionLevel.IPv6, (SocketOptionName)27, 0);
m_listener.Bind(new IPEndPoint(IPAddress.IPv6Any, 943));
m_listener.Listen(10);
m_listener.BeginAccept(new AsyncCallback(OnConnection), null);
}
// Called when we receive a connection from a client
public void OnConnection(IAsyncResult res)
{
Socket client = null;
try
{
client = m_listener.EndAccept(res);
}
catch (SocketException)
{
return;
}
// handle this policy request with a PolicyConnection
PolicyConnection pc = new PolicyConnection(client, m_policy);
// look for more connections
m_listener.BeginAccept(new AsyncCallback(OnConnection), null);
}
public void Close()
{
m_listener.Close();
}
}
public class Program
{
static void Main(string[] args)
{
if (args.Length == 0)
{
Console.WriteLine("usage: PolicyServer.exe PolicyFile.xml");
return;
}
PolicyServer ps = new PolicyServer(args[0]);
System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite);
}
}
}
浙公网安备 33010602011771号