Поделиться через


HttpCookieSession (сессия HTTP cookie)

В примере HttpCookieSession показано, как создать пользовательский канал протокола для использования HTTP-файлов cookie для управления сеансами. Этот канал обеспечивает обмен данными между службами Windows Communication Foundation (WCF) и клиентами ASMX или между клиентами WCF и службами ASMX.

Когда клиент вызывает веб-метод в веб-службе ASMX, основанной на сеансе, подсистема ASP.NET выполняет следующие действия:

  • Создает уникальный идентификатор (идентификатор сеанса).

  • Создает объект сеанса и связывает его с уникальным идентификатором.

  • Добавляет уникальный идентификатор в заголовок ответа HTTP Set-Cookie и отправляет его клиенту.

  • На последующих вызовах клиент определяется по идентификатору сеанса, который он отправляет.

Клиент включает этот идентификатор сеанса в последующие запросы к серверу. Сервер использует идентификатор сеанса от клиента для загрузки соответствующего объекта сеанса для текущего контекста HTTP.

Шаблон обмена сообщениями канала HttpCookieSession

Этот пример включает поддержку сеансов для сценариев, похожих на ASMX. В нижней части стека каналов у нас есть http-транспорт, который поддерживает IRequestChannel и IReplyChannel. Это задание канала для предоставления сеансов более высоким уровням стека каналов. В примере реализованы два канала (IRequestSessionChannel и IReplySessionChannel), которые поддерживают сеансы.

Канал обслуживания

Пример предоставляет канал сервиса в классе HttpCookieReplySessionChannelListener. Этот класс реализует IChannelListener интерфейс и преобразует IReplyChannel канал из нижнего стека в стек IReplySessionChannelканалов. Этот процесс можно разделить на следующие части:

  • При открытии прослушивателя каналов он принимает внутренний канал из внутреннего прослушивателя. Так как внутренний слушатель является слушателем датаграмм, и время существования принятого канала отделено от времени существования слушателя, мы можем закрыть внутренний слушатель и удерживать только внутренний канал.

                this.innerChannelListener.Open(timeoutHelper.RemainingTime());
    this.innerChannel = this.innerChannelListener.AcceptChannel(timeoutHelper.RemainingTime());
    this.innerChannel.Open(timeoutHelper.RemainingTime());
    this.innerChannelListener.Close(timeoutHelper.RemainingTime());
    
  • После завершения открытого процесса мы настроим цикл сообщений для получения сообщений из внутреннего канала.

    IAsyncResult result = BeginInnerReceiveRequest();
    if (result != null && result.CompletedSynchronously)
    {
       // do not block the user thread
       this.completeReceiveCallback ??= new WaitCallback(CompleteReceiveCallback);
       ThreadPool.QueueUserWorkItem(this.completeReceiveCallback, result);
    }
    
  • При поступлении сообщения канал службы проверяет идентификатор сеанса и демультиплексирует его на соответствующий канал сеанса. Прослушиватель каналов поддерживает словарь, который сопоставляет идентификаторы сеанса с сеансовыми каналами.

    Dictionary<string, IReplySessionChannel> channelMapping;
    

Класс HttpCookieReplySessionChannel реализует IReplySessionChannel. Высшие уровни стека канала вызывают метод ReceiveRequest для чтения запросов этого сеанса. Каждый канал сеанса имеет очередь частных сообщений, которую заполняет канал службы.

InputQueue<RequestContext> requestQueue;

В случае, если кто-то вызывает ReceiveRequest метод и нет сообщений в очереди сообщений, канал ожидает указанного времени, прежде чем завершить работу. Это очищает каналы сеансов, созданные для клиентов, отличных от WCF.

Мы используем channelMapping для отслеживания ReplySessionChannels, и не закрываем базовые innerChannel, пока все принятые каналы не будут закрыты. Этот способ HttpCookieReplySessionChannel может существовать за пределами времени существования HttpCookieReplySessionChannelListener. Мы также не должны беспокоиться о том, как прослушиватель получает мусор, собранный под нами, потому что принятые каналы сохраняют ссылку на их прослушиватель через OnClosed обратный вызов.

Клиентский канал

Соответствующий клиентский канал находится в классе HttpCookieSessionChannelFactory. Во время создания канала фабрика каналов упаковывает внутренний канал запроса с помощью HttpCookieRequestSessionChannel. Класс HttpCookieRequestSessionChannel перенаправит вызовы в базовый канал запросов. Когда клиент закрывает прокси-сервер, отправляет сообщение службе, HttpCookieRequestSessionChannel указывающее, что канал закрыт. Таким образом, стек служебных каналов может без проблем завершить работу канала сеанса, который используется.

Элемент привязки и привязка

После создания каналов службы и клиента необходимо интегрировать их в среду выполнения WCF. Каналы взаимодействуют с WCF через привязки и элементы привязки. Привязка состоит из одного или нескольких элементов привязки. WCF предлагает несколько системных привязок; например, BasicHttpBinding или WSHttpBinding. Класс HttpCookieSessionBindingElement содержит реализацию элемента привязки. Он переопределяет методы создания прослушивателя каналов и фабрики каналов для создания необходимых экземпляров прослушивателя каналов или фабрики каналов.

В примере используются утверждения политики для описания службы. Это позволяет примеру публиковать требования к каналу для других клиентов, которые могут воспользоваться услугой. Например, этот элемент привязки публикует утверждения политики, чтобы сообщить потенциальным клиентам, что он поддерживает сеансы. Поскольку пример включает свойство ExchangeTerminateMessage в конфигурацию элемента привязки, он добавляет необходимые утверждения, чтобы показать, что служба поддерживает дополнительное действие обмена сообщениями для терминирования сеанса. Затем клиенты могут использовать это действие. В следующем коде WSDL показаны утверждения политики, созданные на основе HttpCookieSessionBindingElement.

<wsp:Policy wsu:Id="HttpCookieSessionBinding_IWcfCookieSessionService_policy" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsp:ExactlyOne>
<wsp:All>
<wspe:Utf816FFFECharacterEncoding xmlns:wspe="http://schemas.xmlsoap.org/ws/2004/09/policy/encoding"/>
<mhsc:httpSessionCookie xmlns:mhsc="http://samples.microsoft.com/wcf/mhsc/policy"/>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>

Класс HttpCookieSessionBinding представляет собой системную привязку, которая использует элемент привязки, описанный ранее.

Добавление канала в систему конфигурации

В этом примере представлены два класса, которые открывают доступ к каналу примера с помощью конфигурации. Первое — BindingElementExtensionElement для HttpCookieSessionBindingElement. Основная реализация делегируется HttpCookieSessionBindingConfigurationElement, который происходит от StandardBindingElement. Имеет HttpCookieSessionBindingConfigurationElement свойства, соответствующие свойствам HttpCookieSessionBindingElement.

Раздел расширения элемента привязки

Этот раздел HttpCookieSessionBindingElementSection является BindingElementExtensionElement, который открывает HttpCookieSessionBindingElement для системы конфигурации. При помощи нескольких переопределений определяется имя раздела конфигурации, тип элемента привязки и способ создания элемента привязки. Затем можно зарегистрировать раздел расширения в файле конфигурации следующим образом:

<configuration>
    <system.serviceModel>
      <extensions>
        <bindingElementExtensions>
          <add name="httpCookieSession"
               type=
"Microsoft.ServiceModel.Samples.HttpCookieSessionBindingElementElement,
                    HttpCookieSessionExtension, Version=1.0.0.0,
                    Culture=neutral, PublicKeyToken=null"/>
        </bindingElementExtensions >
      </extensions>

      <bindings>
      <customBinding>
        <binding name="allowCookiesBinding">
          <textMessageEncoding messageVersion="Soap11WSAddressing10" />
          <httpCookieSession sessionTimeout="10" exchangeTerminateMessage="true" />
          <httpTransport allowCookies="true" />
        </binding>
      </customBinding>
      </bindings>
    </system.serviceModel>
</configuration>

Тестовый код

Тестовый код для использования этого примера транспорта доступен в каталогах клиента и службы. Он состоит из двух тестов— один тест использует привязку с allowCookies установленным значением true на клиенте. Второй тест позволяет явно завершить работу (используя обмен сообщениями для завершения) на уровне связывания.

При запуске примера вы увидите следующие выходные данные:

Simple binding:
AddItem(10000,2): ItemCount=2
AddItem(10550,5): ItemCount=7
RemoveItem(10550,2): ItemCount=5
Items
10000, 2
10550, 3
Smart binding:
AddItem(10000,2): ItemCount=2
AddItem(10550,5): ItemCount=7
RemoveItem(10550,2): ItemCount=5
Items
10000, 2
10550, 3

Press <ENTER> to terminate client.

Настройка, сборка и запуск примера

  1. Установите ASP.NET 4.0 с помощью следующей команды.

    %windir%\Microsoft.NET\Framework\v4.0.XXXXX\aspnet_regiis.exe /i /enable
    
  2. Убедитесь, что вы выполнили процедуру настройки One-Time для образцов Windows Communication Foundation.

  3. Чтобы создать решение, следуйте инструкциям по созданию примеров Windows Communication Foundation.

  4. Чтобы запустить пример в конфигурации с одним или несколькими компьютерами, следуйте инструкциям в запуска примеров Windows Communication Foundation.