2

応答ヘッダーに「Set-Cookie」属性を追加することで、WCF サービスの発信応答に複数の Cookie を追加することができました。それはうまく機能し、Cookieは1つのCookieがあり、複数のCookieがない場合にのみ、後続のすべてのリクエストで利用できます.以下の実装を参照してください. 応答で更新する保留中の Cookie がある場合、すべての WCF サービス メソッド呼び出しに Cookie を追加するために、IDispatchMessageInspector インターフェイスを実装して応答ヘッダーに Cookie を追加しています。

応答ヘッダーと要求ヘッダーの Cookie 出力のサンプル

1 クッキー: foo=testcookie1; path=/ --> 2 つ以上の Cookie を呼び出す後続のすべてのリクエストで使用可能: foo=testcookie1; パス=/;、foo2=testcookie2; パス=/;、foo3=testcookie3; パス=/; --> --> 後続のすべてのリクエスト呼び出しで最初の Cookie のみが利用可能で、他の 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));
        }
    }
}
4

1 に答える 1

3

Web プロキシを構築しているときに、同じ問題に遭遇しました。Set-Cookie ヘッダーをターゲット HttpWebResponse からプロキシ HttpListenerResponse にリレーする必要がありました。Set-Cookie ヘッダーに複数の Cookie がある場合、最初の Cookieのみがブラウザーに登録されます。

ヘッダーの値のセット (または、あなたの場合は Cookie のコレクション) を反復処理し、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));
于 2011-10-20T02:28:51.510 に答える