参考资料:

http://www.cnblogs.com/czcz1024/p/3333138.html

http://megakemp.com/2009/02/06/managing-shared-cookies-in-wcf/

首先使用的绑定 必须允许Cookie传播

      <wsHttpBinding>
        <binding  closeTimeout="00:01:30" openTimeout="00:01:30"  maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647"
           transactionFlow="true" allowCookies="True">
          <reliableSession enabled="true" />
          
          <security mode= "None">
          </security>
        </binding>
      </wsHttpBinding> 其次
服务需要基于ASP.NET 的激活进行host
    <!--运行服务以ASP.NET激活模式激活服务-->
    <serviceHostingEnvironment aspNetCompatibilityEnabled ="true" multipleSiteBindingsEnabled="true" /> 第三 服务的实现 ,基于属性的声明允许以ASP.NET的方式访问
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    public class AddressWCFService : IAddressWCFService
第四 最关键的一部,实现客户端的消息发送 响应拦截器
	/// <summary>
/// Gets the singleton <see cref="ClientIdentityMessageInspector" /> instance.
/// </summary>
public static CookieManagerMessageInspector Instance
{
get
{
if (instance == null)
{
instance = new CookieManagerMessageInspector();
} return instance;
}
} /// <summary>
/// Inspects a message after a reply message is received but prior to passing it back to the client application.
/// </summary>
/// <param name="reply">The message to be transformed into types and handed back to the client application.</param>
/// <param name="correlationState">Correlation state data.</param>
public void AfterReceiveReply(ref Message reply, object correlationState)
{
HttpResponseMessageProperty httpResponse =
reply.Properties[HttpResponseMessageProperty.Name] as HttpResponseMessageProperty; if (httpResponse != null)
{
string cookie = httpResponse.Headers[HttpResponseHeader.SetCookie]; if (!string.IsNullOrEmpty(cookie))
{
this.sharedCookie = cookie;
}
}
} /// <summary>
/// Inspects a message before a request message is sent to a service.
/// </summary>
/// <param name="request">The message to be sent to the service.</param>
/// <param name="channel">The client object channel.</param>
/// <returns>
/// <strong>Null</strong> since no message correlation is used.
/// </returns>
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
HttpRequestMessageProperty httpRequest; // The HTTP request object is made available in the outgoing message only when
// the Visual Studio Debugger is attacched to the running process
if (!request.Properties.ContainsKey(HttpRequestMessageProperty.Name))
{
request.Properties.Add(HttpRequestMessageProperty.Name, new HttpRequestMessageProperty());
} httpRequest = (HttpRequestMessageProperty)request.Properties[HttpRequestMessageProperty.Name];
httpRequest.Headers.Add(HttpRequestHeader.Cookie, this.sharedCookie); return null;
} 最后一步:为客户端的Behavior添加行为扩展
	public class CookieManagerEndpointBehavior : IEndpointBehavior
{
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
return;
} public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
clientRuntime.MessageInspectors.Add(CookieManagerMessageInspector.Instance);
} public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
return;
} public void Validate(ServiceEndpoint endpoint)
{
return;
}
}
到此 就可以配置客户端ClientProxy代理的实例 进行Cookie的传播共享了。下面是客户端的Behavior的扩展
    <behaviors>
      <endpointBehaviors>
        <behavior name="CookieBehaviorConfig">
           <clear/>
          <!--注册行为扩展-->
          <CookieBehavior />
        </behavior>
      </endpointBehaviors>
    </behaviors>
    
    <!--扩展 客户端的Behavior-->
    <extensions>
      <behaviorExtensions>
        <add name="CookieBehavior" type="Smart.Client.CookieManager.CookieManagerBehaviorExtension, Smart.Client.CookieManager, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
      </behaviorExtensions>
    </extensions>
以下是作者原文,本文基于作者思路而来,谢谢。

wcf读写cookie

 

一般来说,web应用的服务端(aspx或mvc的action)调用wcf时,是一个服务与服务的通讯,而不是客户端(浏览器)与服务器的通讯。

这种情况下,如果要在wcf端处理客户端的cookie,就需要做一些额外的开发。

首先,在wcf的web.config里,需要启用

<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />

之后,wcf的实现类需要加attribute

[AspNetCompatibilityRequirements(RequirementsMode= AspNetCompatibilityRequirementsMode.Required)]

做完上面的两步,在wcf具体的方法里就可以使用HttpContext.Current .Resposne/.Request来读写cookie了。

但是,正如上面所说,这是一个服务器与服务器的通讯,客户端(web应用)并不会自动发送cookie到wcf。所以客户端还得做更多的工作

核心在IClientMessageInspector 这个接口,他有

BeforeSendRequest和AfterReceiveReply两个方法。

我们的目的是在beforeSendRequest时,在请求中加入cookie信息,在AfterReciveReply方法中,从响应中获取要设置的cookie,并真正设置到客户端(浏览器)

public class CookieMessageInspector : IClientMessageInspector
新建一个类,来实现接口
   1: public object BeforeSendRequest(ref Message request,System.ServiceModel.IClientChannel channel)
   2: {
   3:     var cookie = GetCookieValue();
   4:  
   5:     HttpRequestMessageProperty httpRequestMessage;
   6:     object httpRequestMessageObject;
   7:  
   8:     if (request.Properties.TryGetValue(HttpRequestMessageProperty.Name, out httpRequestMessageObject))
   9:     {
  10:         httpRequestMessage = httpRequestMessageObject as HttpRequestMessageProperty;
  11:         if (string.IsNullOrEmpty(httpRequestMessage.Headers["Cookie"]))
  12:         {
  13:             httpRequestMessage.Headers["Cookie"] = cookie;
  14:         }
  15:     }
  16:     else
  17:     {
  18:         httpRequestMessage = new HttpRequestMessageProperty();
  19:         httpRequestMessage.Headers.Add("Cookie", cookie);
  20:         request.Properties.Add(HttpRequestMessageProperty.Name, httpRequestMessage);
  21:     }
  22:  
  23:     return null;
  24: }

我们需要把cookie值,转化成字符串进行传递,cookie名=cookie值这样的形式,多个cookie用分号(;)分隔。

我们新建的这个类,要如何使用呢,他需要在一个behavior中调用。所以我们还得建立一个behavior

public class CookieBehavior : IEndpointBehavior

实现接口IEndpointBehavior,并且在方法ApplyClientBehavior中加入我们刚才的类

public void ApplyClientBehavior(ServiceEndpoint serviceEndpoint,ClientRuntime behavior)
{
behavior.MessageInspectors.Add(new CookieMessageInspector());
}

其他需要实现的方法,直接return即可

通过vs添加服务引用,他会自动生成一个代理类。在new这个代理类之后,加入我们新建的behavior

var client = new TestSvc.TestSvcClient();
CookieBehavior b = new CookieBehavior();
client.Endpoint.Behaviors.Add(b);

之后,我们调用方法,就会把cookie信息传递到wcf了。

到目前为止,我们可以解决web向wcf传递当前cookie,wcf可以读取cookie。

下面我们解决在wcf中设置cookie。

同样的原理,在读取的时候,我们是在BeforeSendRequest中实现的,那写入则需要在AfterReceiveReply中实现了。

在wcf中使用

HttpContext.Current.Response.Cookies.Add(new HttpCookie("test123", "123"));

类似这样的代码设置cookie,他在响应的header里会有Set-Cookie,我们只需要处理Set-Cookie里面的内容就可以了。

在写入多个cookie时,与读操作不同,这里是用逗号(,)分隔的,并且默认他会带cookie的path,如果你设置了cookie的domain,过期时间等,他也会传递,并且同一个cookie的若干属性之间是用分号(;)分隔的

   1: public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply,object correlationState)
   2: {
   3:     if (reply.Properties.ContainsKey("httpResponse"))
   4:     {
   5:         HttpResponseMessageProperty httpResponse = reply.Properties["httpResponse"] as HttpResponseMessageProperty;
   6:  
   7:         if (httpResponse != null)
   8:         {
   9:             string cookie = httpResponse.Headers.Get("Set-Cookie");
  10:             if (!string.IsNullOrEmpty(cookie))
  11:             {
  12:                 //解析并设置cookie
  13:             }
  14:         }
  15:     }
  16: }

具体如何解析,就是字符串操作,就不细说了。

以上方式可以实现web应用的服务器端与wcf通讯时,附带客户端(浏览器)的cookie信息,进行读写操作。

但是每次都需要对client进行设置,相对比较麻烦。我们可以通过web.config中的配置来让client自动加入behavior。

同样,我们需要下面这样的一个类

public class CookieBehaviorExtensionElement :BehaviorExtensionElement
{
protected override object CreateBehavior()
{
return new CookieBehavior();
} public override Type BehaviorType
{
get { return typeof(CookieBehavior); }
}
}

之后,在web项目的web.config中

<system.serviceModel>

此节点下,首先需要加入

<extensions>
<behaviorExtensions>
<add name="CookieBehavior" type="webhost.CookieBehaviorExtensionElement, webhost, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</behaviorExtensions>
</extensions>
注意type是的写法,需要根据自己项目的命名空间来进行修改
之后
<behaviors>
<endpointBehaviors>
<behavior name="CookieBehaviorConfig">
<CookieBehavior />
</behavior>
</endpointBehaviors>
</behaviors>

黄色部分,为extensions中我们添加的那条的name
最后
<endpoint address="http://localhost:5351/testSvc.svc" binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_ITestSvc" contract="TestSvc.ITestSvc"
name="BasicHttpBinding_ITestSvc" behaviorConfiguration="CookieBehaviorConfig" />

设置endpoint的behaviorConfiguration为behaviors节中添加的behavior的name

 

如此,我们就可以不用每次new client之后在去设置它的behavior了

WCF 基于Cookie的登录验证回传问题的解决的更多相关文章

  1. 基于session和cookie的登录验证(CBV模式)

    基于session和cookie的登录验证(CBV模式) urls.py """cookie_session URL Configuration The `urlpatt ...

  2. [转载:Q1mi]Bootstrap和基于Bootstrap的登录验证示例

    转载自:Q1mi Bootstrap介绍 Bootstrap是Twitter开源的基于HTML.CSS.JavaScript的前端框架. 它是为实现快速开发Web应用程序而设计的一套前端工具包. 它支 ...

  3. SpringBoot实现基于token的登录验证

    一.SpringBoot实现基于token的登录验证 基于token的登录验证实现原理:客户端通过用户名和密码调用登录接口,当验证数据库中存在该用户后,将用户的信息按照token的生成规则,生成一个字 ...

  4. WCF基于Cookie回传的系列(概述)

    1  WCF的基本知识(不作细述,园子里有很多的经典的文章系列) 2 WCF的执行过程 3 让服务通信像浏览器发送请求应答一样回传Cookie,并实现Cookie在不同的服务间共享 4  基于共享后的 ...

  5. Jmeter上传文件、cookie、登录验证

    2.11选择http请求   3.0 cookie 域:十九服务器ip或者域名 路径就是接口路径 登录验证:

  6. 浏览器禁用Cookie,基于Cookie的会话跟踪机制失效的解决的方法

    当浏览器禁用Cookies时.基于Cookie的会话跟踪机制就会失效.解决的方法是利用URL重写机制跟踪用户会话. 在使用URL重写机制的时候须要注意.为了保证会话跟踪的正确性,全部的链接和重定向语句 ...

  7. ASP.NET Cookie的登录验证

    做用户登录,我一直用form验证的方式.有时候,为了节省时间,用户希望用户名输入框能够记住用户名,省得下次重新输入.这个时候光用form验证是不行的,因为form验证的话,用户一退出系统就失效了,所以 ...

  8. 基于cookie实现用户验证

    #!/usr/bin/env python import tornado.ioloop import tornado.web class IndexHander(tornado.web.Request ...

  9. 基于cookie或session的登陆验证之安全性问题

    因为session是关了浏览器就没了.所以可以通过cookie结合session方法来做验证! 第一次登陆,生成一个cookie,保存一些加密的帐号信息,然后再生成一个session 这样去其他需要验 ...

随机推荐

  1. Delphi EurekaLog 调试内存泄露方法

    要使用EurekaLog进行内存泄露检测,需要手动开启"EurekaLog Options..."下的"Advanced Options"旁的"Mem ...

  2. cf500B New Year Permutation

    B. New Year Permutation time limit per test 2 seconds memory limit per test 256 megabytes input stan ...

  3. jTemplates——学习(1)

    这里介绍一个基于jQuery开发的模板引擎. jTemplates目前最新的版本是0.7.8,由tPython开发.官方网站:http://jtemplates.tpython.com 两个附件, 一 ...

  4. MySQL 二进制日志(Binary Log)

    同大多数关系型数据库一样,日志文件是MySQL数据库的重要组成部分. MySQL有几种不同的日志文件.通常包括错误日志文件,二进制日志,通用日志,慢查询日志,等等.这些日志能够帮助我们定位mysqld ...

  5. 图表插件--jqplot交互演示样例

    简单交互 在之前的学习中,我们已经能够绘制各种类型的图表,也能够给图表加入不同的组件,如标题.图例等等.但这些图表仅仅能用于展示数据,一旦希望对图表有所操作--比方查看数据明细--就显得束手无策了.事 ...

  6. Welcome to Apache™ Hadoop®!

    What Is Apache Hadoop? Getting Started Download Hadoop Who Uses Hadoop? News 15 October, 2013: relea ...

  7. HTML5硕士学习笔记

    如今,该集团经过培训的同事给大家HTML5,他出席了两个5训练日,大概过一次给我们,在一个很形象.同事们更感兴趣的是. 课后共享所有的课件.在热情的新技术,我想工作有一个良好的早晨,我决定重新学习课件 ...

  8. Ignatius and the Princess III --undo

    Ignatius and the Princess III Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 65536/32768K (J ...

  9. Java基础知识强化60:经典查找之二分查找

    1. 二分查找       二分查找又称折半查找,优点是比较次数少,查找速度快,平均性能好:其缺点是要求待查表为有序表,且插入删除困难.因此,折半查找方法适用于不经常变动而查找频繁的有序列表. 比较 ...

  10. Java基本类型与包装类

    存储方式及位置的不同,基本类型是直接存储变量的值保存在堆栈中能高效的存取,封装类型需要通过引用指向实例,具体的实例保存在堆中   Java语言提供了八种基本类型.六种数字类型(四个整数型,两个浮点型) ...