WCF 中安全性的最佳做法

以下部分列出了使用 Windows Communication Foundation (WCF) 创建安全应用程序时要考虑的最佳做法。 有关安全性的详细信息,请参阅 安全注意事项数据安全注意事项以及 元数据的安全注意事项

识别使用 SPN 执行 Windows 身份验证的服务

可以使用用户主体名称(UPN)或服务主体名称(SPN)标识服务。 在计算机帐户(如网络服务)下运行的服务具有与它们正在运行的计算机对应的 SPN 标识。 在用户帐户下运行的服务具有与运行所在用户帐户对应的 UPN 标识,而可以使用 setspn 工具将 SPN 分配给用户帐户。 配置服务,以便通过 SPN 识别服务,并配置连接到服务的客户端以使用该 SPN 会使某些攻击更加困难。 此指导信息适用于使用 Kerberos 或 SSPI 协商的绑定。 如果 SSPI 回退到 NTLM,客户端仍应指定 SPN。

验证 WSDL 中的服务标识

WS-SecurityPolicy 允许服务在元数据中发布有关其自己的标识的信息。 通过 svcutil 或其他方法 WsdlImporter检索时,此标识信息将转换为 WCF 服务终结点地址的标识属性。 如果客户端不验证这些服务标识的正确性和有效性,就相当于绕过了服务身份验证。 恶意服务可以通过更改其 WSDL 中声明的标识来利用此类客户端执行凭据转发和其他“中间人”攻击。

使用 X509 证书而不是 NTLM

WCF 为对等身份验证提供两种机制:X509 证书(由对等通道使用)和 Windows 身份验证(其中 SSPI 协商从 Kerberos 降级为 NTLM)。 建议使用密钥大小为1024位或以上的证书认证,而不是NTLM,原因如下:

  • 相互身份验证的可用性,

  • 使用更强大的加密算法,以及

  • 不易使用转发的 X509 凭据。

始终在模拟后还原

在使用启用客户端模拟的 API 时,应确保还原为原始标识。 例如,使用WindowsIdentityWindowsImpersonationContext时,使用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 方法,可以在控制极严的范围中使用模拟。 与此相反的是,使用 ImpersonationOperationBehaviorAttribute 属性允许对整个操作的范围进行模拟。 尽可能使用更精确的 Impersonate 方法来控制冒充的范围。

从受信任的源获取元数据

请确保信任元数据的来源,并确保没有人篡改元数据。 使用 HTTP 协议检索到的元数据是以明文形式发送的,可能被篡改。 如果服务使用 HttpsGetEnabledHttpsGetUrl 属性,请使用服务创建者提供的 URL,以使用 HTTPS 协议下载数据。

以安全的方式发布元数据

若要防止篡改服务的已发布元数据,请使用传输或消息级安全性保护元数据交换终结点。 有关详细信息,请参阅 发布元数据终结点如何使用代码发布服务的元数据

确保使用本地颁发者

如果为某个绑定指定了颁发者地址及其绑定,则不使用本地颁发者来处理使用该绑定的终结点。 希望始终使用本地颁发者的客户端应确保它们不使用此类绑定,或者修改绑定,使颁发者地址为 null。

SAML 令牌大小配额

当安全断言标记语言(SAML)令牌在消息中序列化时,无论是由安全令牌服务(STS)颁发,还是当客户端将其作为身份验证的一部分提供给服务时,最大消息大小配额必须足够大,以适应 SAML 令牌和其他消息部分。 在正常情况下,默认消息大小配额已足够。 但是,当 SAML 令牌由于包含数以百计的声明而过于庞大时,您可能需要提高配额,以便容纳序列化的令牌。 有关配额的详细信息,请参阅 数据的安全注意事项

在自定义绑定上将 SecurityBindingElement.IncludeTimestamp 设置为 True

创建自定义绑定时,必须将 IncludeTimestamp 设置为 true。 否则,如果 IncludeTimestamp 设置为 false,并且客户端正在使用基于非对称密钥的令牌(如 X509 证书),则不会对消息进行签名。

另请参阅