如何:为安全会话创建安全上下文令牌

通过在安全会话中使用有状态安全上下文令牌 (SCT),可以使该会话避免因为重新使用服务而受到影响。例如,如果在安全会话中使用了无状态 SCT 并且 Internet 信息服务 (IIS) 被重置,则与该服务相关联的会话数据将丢失。这些会话数据包括一个 SCT 令牌缓存。因此,当客户端下一次向该服务发送无状态 SCT 时,将返回错误,这是因为无法检索到与该 SCT 相关联的密钥。但是,如果使用有状态 SCT,则与该 SCT 相关联的密钥将包含在该 SCT 中。由于密钥包含在 SCT 中并因而包含在消息中,因此安全会话不会因为重新使用服务而受到影响。默认情况下,Windows Communication Foundation (WCF) 在安全会话中使用无状态 SCT。本主题详细介绍如何在安全会话中使用有状态 SCT。

ms731814.note(zh-cn,VS.100).gif注意:
如果安全会话涉及到派生自 IDuplexChannel 的协定,则无法在该安全会话中使用有状态 SCT。

ms731814.note(zh-cn,VS.100).gif注意:
对于在安全会话中使用有状态 SCT 的应用程序,服务的线程标识必须是具有关联用户配置文件的用户帐户。如果服务在不具有用户配置文件的帐户下运行(如 Local Service),则可能引发异常。

ms731814.note(zh-cn,VS.100).gif注意:
当需要在 Windows XP 上进行模拟时,请不要在安全会话中使用有状态 SCT。如果在模拟时使用有状态 SCT,则会引发 InvalidOperationException。有关更多信息,请参见 不支持的方案.

在安全会话中使用有状态 SCT

  • 创建一个自定义绑定,该绑定指定由使用有状态 SCT 的安全会话来保护 SOAP 消息。

    1. 通过向服务的配置文件中添加一个 customBinding Element,定义一个自定义绑定。

      <customBinding>
      
    2. 将一个 <binding> 子元素添加到 customBinding Element中。

      通过在配置文件中将 name 属性设置为一个唯一的名称,指定一个绑定名称。

      <binding name="StatefulSCTSecureSession">
      
    3. 通过将一个 security element of customBinding 子元素添加到 customBinding Element,指定发送到此服务以及从此服务发送出去的消息的身份验证模式。

      通过将 authenticationMode 属性设置为 SecureConversation,指定使用安全会话。通过将 requireSecurityContextCancellation 属性设置为 false,指定使用有状态 SCT。

      <security authenticationMode="SecureConversation"
                requireSecurityContextCancellation="false">
      
    4. 通过将一个 secureConversationBootstrap element子元素添加到 security element of customBinding,指定在建立安全会话时如何对客户端进行身份验证。

      通过设置 authenticationMode 属性,指定如何对客户端进行身份验证。

      <secureConversationBootstrap authenticationMode="UserNameForCertificate" />
      
    5. 指定消息编码,方法是添加一个编码元素,如 textMessageEncoding element

      <textMessageEncoding />
      
    6. 指定传输,方法是添加一个传输元素,如 httpTransport element

      <httpTransport />
      

    下面的代码示例使用配置来指定一个自定义绑定,消息可以将该绑定与安全会话中的有状态 SCT 结合使用。

    <customBinding>
      <binding name="StatefulSCTSecureSession">
        <security authenticationMode="SecureConversation"
                  requireSecurityContextCancellation="false">
          <secureConversationBootstrap authenticationMode="UserNameForCertificate" />
        </security>
        <textMessageEncoding />
        <httpTransport />
      </binding>
    </customBinding>
    

示例

下面的代码示例创建一个自定义绑定,该绑定使用 MutualCertificate 身份验证模式启动安全会话。

Dim security As SecurityBindingElement = SecurityBindingElement.CreateMutualCertificateBindingElement()


' Use a secure session and specify that stateful SecurityContextToken security tokens are used.
security = SecurityBindingElement.CreateSecureConversationBindingElement(security, False)

' Specify whether derived keys are needed.      
security.SetKeyDerivation(True)

' Create the custom binding.
Dim myBinding As New CustomBinding(security, New HttpTransportBindingElement())

' Create the Type instances for later use and the Uri for 
' the base address.
Dim contractType As Type = GetType(ICalculator)
Dim serviceType As Type = GetType(Calculator)
Dim baseAddress As New Uri("https://localhost:8036/serviceModelSamples/")

' Create the ServiceHost and add an endpoint, then start
' the service.
Dim myServiceHost As New ServiceHost(serviceType, baseAddress)
myServiceHost.AddServiceEndpoint(contractType, myBinding, "secureCalculator")
myServiceHost.Open()
SecurityBindingElement security = SecurityBindingElement.CreateMutualCertificateBindingElement();

// Use a secure session and specify that stateful SecurityContextToken security tokens are used.
security = SecurityBindingElement.CreateSecureConversationBindingElement(security, false);

// Specify whether derived keys are needed.      
security.SetKeyDerivation(true);

// Create the custom binding.
CustomBinding myBinding = new CustomBinding(security, new HttpTransportBindingElement());

// Create the Type instances for later use and the Uri for 
// the base address.
Type contractType = typeof(ICalculator);
Type serviceType = typeof(Calculator);
Uri baseAddress = new
    Uri("https://localhost:8036/serviceModelSamples/");

// Create the ServiceHost and add an endpoint, then start
// the service.
ServiceHost myServiceHost =
    new ServiceHost(serviceType, baseAddress);
myServiceHost.AddServiceEndpoint
    (contractType, myBinding, "secureCalculator");
myServiceHost.Open();

在将 Windows 身份验证与有状态 SCT 结合起来使用时,WCF 不使用实际调用方的标识来填充 WindowsIdentity 属性,而是将该属性设置为匿名。由于 WCF 安全必须为来自传入 SCT 的每个请求重新创建服务安全上下文的内容,因此服务器不会跟踪内存中的安全会话。因为不可能将 WindowsIdentity 实例序列化为 SCT,所以 WindowsIdentity 属性返回一个匿名标识。

下面的配置演示这一行为。

<customBinding>
  <binding name="Cancellation">
       <textMessageEncoding />
        <security 
            requireSecurityContextCancellation="false">
              <secureConversationBootstrap />
      </security>
    <httpTransport />
  </binding>
</customBinding>

另请参见

其他资源

<custombinding>