WCF 中安全性的最佳做法
以下各节列出了在使用 Windows Communication Foundation (WCF) 创建安全应用程序时应考虑的最佳做法。 有关安全性的详细信息,请参阅安全注意事项、数据的安全注意事项和元数据的安全注意事项。
服务可以使用用户主体名称 (UPN) 或服务主体名称 (SPN) 来标识。 使用计算机帐户运行的服务(如网络服务)具有 SPN 标识,该标识对应于正在运行它们的计算机。 使用用户帐户运行的服务具有 UPN 标识,该标识对应于它们正在以其身份运行的用户,但可以使用 setspn
工具为该用户帐户分配一个 SPN。 配置服务以便可以通过 SPN 标识它,同时将连接到该服务的客户端配置为使用该 SPN,这可以提高对某些攻击的抵御能力。 此指导信息适用于使用 Kerberos 或 SSPI 协商的绑定。 即使 SSPI 降级为 NTLM,客户端应仍指定 SPN。
WS-SecurityPolicy 允许服务在元数据中发布有关其自身标识的信息。 通过 svcutil
或其他方法(如 WsdlImporter)进行检索时,此标识信息将转换为 WCF 服务终结点地址的标识属性。 若客户端不验证这些服务标识是否正确、有效,则实际上是跳过了服务身份验证。 恶意服务可以通过更改其 WSDL 中声称的标识,利用此类客户端来执行凭据转发和其他“中间人”攻击。
WCF 为对等身份验证提供两种机制:X509 证书(由对等通道使用)和 Windows 身份验证(其中 SSPI 协商从 Kerberos 降级为 NTLM)。 由于以下几个原因,使用 1024 位或更多位的密钥、基于证书的身份验证优于 NTLM:
提供相互身份验证;
使用更强的加密算法;以及
不易使用转发的 X509 凭据。
在使用启用客户端模拟的 API 时,应确保还原为原始标识。 例如,在使用 WindowsIdentity 和 WindowsImpersonationContext 时使用 C# using
语句或 Visual Basic Using
语句,如以下代码中所示。 WindowsImpersonationContext 类实现 IDisposable 接口,因此,一旦代码离开 using
块,公共语言运行库 (CLR) 就会自动还原到原始标识。
WindowsIdentity identity = ServiceSecurityContext.Current.WindowsIdentity;
using (identity.Impersonate())
{
// Run code under the caller's identity.
}
Dim identity = ServiceSecurityContext.Current.WindowsIdentity
Using identity.Impersonate()
' Run code under the caller's identity.
End Using
通过使用 Impersonate 类的 WindowsIdentity 方法,可以在控制极严的范围中使用模拟。 与此相反的是,使用 Impersonation 的 OperationBehaviorAttribute 属性允许对整个操作的范围进行模拟。 只要有可能,应使用更精确的 Impersonate 方法来控制模拟的范围。
确保信任元数据的源,并确保没有人篡改元数据。 使用 HTTP 协议检索到的元数据是以明文形式发送的,可能被篡改。 如果服务使用 HttpsGetEnabled 和 HttpsGetUrl 属性,请根据服务创建者提供的 URL,使用 HTTPS 协议下载数据。
要防止篡改服务的已发布元数据,可使用传输或消息级安全来保证元数据交换终结点的安全。 有关详细信息,请参阅发布元数据终结点和如何:使用代码发布服务的元数据。
如果为某个给定绑定指定了颁发者地址和绑定,则不对使用该绑定的终结点使用本地颁发者。 希望始终使用本地颁发者的客户应确保不使用这样的绑定,或修改绑定以使颁发者地址为 null。
如果在消息中序列化安全断言标记语言 (SAML) 令牌,无论这些令牌是由安全令牌服务 (STS) 颁发的,还是客户端将其作为身份验证的一部分提交给服务,最大消息大小配额都必须足够大,以便能够容纳 SAML 令牌和其他消息部分。 正常情况下,默认消息大小配额足够使用。 但是,当 SAML 令牌由于包含数以百计的声明而过于庞大时,您可能需要提高配额,以便容纳序列化的令牌。 有关配额的详细信息,请参阅数据的安全注意事项。
创建自定义绑定时,必须将 IncludeTimestamp 设置为 true
。 否则如果将 IncludeTimestamp 设置为 false
,并且客户端使用基于非对称密钥的令牌(例如 X509 证书),则不会对消息进行签名。