Проблема с добавлением нескольких файлов cookie для ответа в службе WCF - PullRequest
2 голосов
/ 28 февраля 2011

Мне удалось добавить несколько файлов cookie в исходящий ответ службы WCF, добавив атрибут «Set-Cookie» в заголовок ответа. Он отлично работает, и cookie доступен во всех последующих запросах, только если есть один cookie, но не для нескольких cookie. Пожалуйста, ознакомьтесь с моей реализацией ниже. Я добавляю файлы cookie в заголовок ответа, реализуя интерфейс IDispatchMessageInspector, чтобы добавить файлы cookie во все вызовы метода службы WCF, если в ответе есть какие-либо ожидающие обновления файлы cookie.

Пример вывода файлов cookie в заголовок ответа и заголовок запроса

1 Cookie: foo = testcookie1; путь = / -> доступен во всех последующих вызовах запроса 2 или более файлов cookie: foo = testcookie1; путь = / ;, foo2 = testcookie2; путь = / ;, foo3 = testcookie3; path = /; -> -> только первый файл cookie, доступный во всех последующих вызовах запроса, но не другие

Например:

после установки файлов cookie мой заголовок ответа будет выглядеть так: Set-Cookie: foo1 = testcookie1;, foo2 = testcookie2 ;, foo3 = testcookie3; . Если я сделаю еще один запрос, то cookie заголовка запроса будет содержать только foo1 = testcookie1; , но не эти файлы cookie foo2 = testcookie2; foo3 = testcookie3; . Это где проблема приходит. Если в заголовке ответа я установил более одного файла cookie, то при последующем вызове запроса он всегда берет только первый файл cookie.

Пожалуйста, помогите мне решить эту проблему. Заранее благодарим за ваши добрые ответы.


РЕАЛИЗАЦИЯ

public class CookieManagerServiceBehaviorAttribute : Attribute, IServiceBehavior
{
    #region IServiceBehavior Members
    public void AddBindingParameters(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
    {
        return;
    }

    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase)
    {
        foreach (ChannelDispatcher channelDispatch in serviceHostBase.ChannelDispatchers)
        {
            foreach (EndpointDispatcher endpointDispatch in channelDispatch.Endpoints)
            {
                endpointDispatch.DispatchRuntime.MessageInspectors.Add(CookieManagerMessageInspector.Instance);
            }
        }
    }

    public void Validate(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase)
    {
        return;
    }
    #endregion
}

public class CookieManagerMessageInspector : IDispatchMessageInspector
{
    private static CookieManagerMessageInspector instance;
    private CookieManagerMessageInspector() { }
    public static CookieManagerMessageInspector Instance
    {
        get
        {
            if (instance == null)
            {
                instance = new CookieManagerMessageInspector();
            }
            return instance;
        }
    }

    public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
    {
        return null;
    }

    public void BeforeSendReply(ref Message reply, object correlationState)
    {
        HttpResponseMessageProperty httpResponse;
        if (!reply.Properties.ContainsKey(HttpResponseMessageProperty.Name))
        {
            reply.Properties.Add(HttpResponseMessageProperty.Name, new HttpResponseMessageProperty());
        }
        httpResponse = (HttpResponseMessageProperty)reply.Properties[HttpResponseMessageProperty.Name];
        foreach (Cookie cookie in RenderContext.Current.PendingCookies)
        {
            if (cookie.Expires > DateTime.Now)
                httpResponse.Headers.Add(HttpResponseHeader.SetCookie, "{0}={1}; expires={2}".StringFormat(cookie.Name, cookie.Value, DateTime.Now.AddYears(1).ToUniversalTime()) + ";");
            else
                httpResponse.Headers.Add(HttpResponseHeader.SetCookie, "{0}={1};".StringFormat(cookie.Name, cookie.Value));
        }
    }
}

1 Ответ

3 голосов
/ 20 октября 2011

При создании веб-прокси я столкнулся с той же проблемой.Мне нужно было передать заголовок Set-Cookie с целевого HttpWebResponse на прокси HttpListenerResponse.Если бы в заголовке Set-Cookie было несколько файлов cookie, тогда только , первый из них был бы зарегистрирован в браузере.

Я смог заставить его работать, когда перебрал набор значенийзаголовка (или в вашем случае коллекции Cookies) и использовал форму response.AppendHeader (header, value).

string[] cookies = response.Headers.GetValues("Set-Cookie");
foreach (string value in cookies)
    clientResponse.AppendHeader("Set-Cookie", value);

Так что в вашем случае я бы изменил конец вашего кода на:

if (cookie.Expires > DateTime.Now)
     httpResponse.AppendHeader(HttpResponseHeader.SetCookie, "{0}={1}; expires={2}".StringFormat(cookie.Name, cookie.Value, DateTime.Now.AddYears(1).ToUniversalTime()) + ";");
else
     httpResponse.AppendHeader(HttpResponseHeader.SetCookie, "{0}={1};".StringFormat(cookie.Name, cookie.Value));
...