我通过在响应标头中添加“Set-Cookie”属性,设法在WCF服务传出响应中添加多个cookie。它工作得很好,只有当有一个cookie而不是多个cookie时,cookie才可用于所有后续请求。请参考我的下面的实现。我通过实现IDispatchMessageInspector接口将cookie添加到响应头中,以便在响应中更新任何挂起的cookie时在所有WCF服务方法调用中添加cookie。
响应标头和请求标头中输出的Cookie示例
1 Cookie: foo = testcookie1; path = / - >在所有后续请求调用中都可用 2个或更多cookie: foo = testcookie1; path = /;,foo2 = testcookie2; path = /;,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));
}
}
}
答案 0 :(得分:3)
在构建Web代理时遇到了同样的问题。我需要将目标HttpWebResponse中的Set-Cookie标头中继到代理HttpListenerResponse。如果Set-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));