参考资料:

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. Android中的ScrollView实现 拖拽反弹效果

    public class BounceScrollView extends ScrollView { private View inner;// 孩子View private float y;// 点 ...

  2. Codeforces Round #277.5 (Div. 2) --E. Hiking (01分数规划)

    http://codeforces.com/contest/489/problem/E E. Hiking time limit per test 1 second memory limit per ...

  3. 自己写的Ext树,Ext3.4,静态全部加载

    var load = function(){ /** * 书籍资料目录 */ var bookIT = new Ext.tree.TreeNode({ text:"IT", lea ...

  4. CentOS 设置mysql的远程访问

    好记性不如烂笔头,记录一下. 安装了MySQL默认是拒绝远程连接的. 首先进入数据库,使用系统数据库mysql. mysql -u root -p mysql #回车,然后输入则使用了系统数据库 接着 ...

  5. 修改cmd的字体

    通常打开的cmd默认的字体比较小,字体只有宋体和新宋体两种,如果要修改,需要通过修改注册表才行. 打开regedit后,找到如下路径HKEY_LOCAL_MACHINE\SOFTWARE\Micros ...

  6. CentOS 6.3下Samba服务器的安装与配置(转)

    CentOS 6.3下Samba服务器的安装与配置   一.简介 Samba是一个能让Linux系统应用Microsoft网络通讯协议的软件,而SMB是Server Message Block的缩写, ...

  7. Hibernate介绍

    1.什么是Hibernate? 首先,Hibernate是数据持久层的一个轻量级框架.数据持久层的框架有很多比如:iBATIS,myBatis,Nhibernate,Siena等等. 并且Hibern ...

  8. 杭州电 1372 Knight Moves(全站搜索模板称号)

    http://acm.hdu.edu.cn/showproblem.php?pid=1372 Knight Moves Time Limit: 2000/1000 MS (Java/Others)   ...

  9. HDU 2159 FATE(全然背包+二维费用背包)

    FATE Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submi ...

  10. MySQL数据库中的哈希加密

    数据库安全是数据库中最为重要的环节,只有确保了数据库中数据的安全,才能够更好的发挥数据库的功能,本文将为大家介绍一种很好的数据库加密方法,即哈希加密. 导读:MySQL数据库加密的方法有很多种,不同的 ...