用户名:
  密    码:
  验证码:
看不清?点击这里换一个
  注    册
  忘记密码   修改密码
首页
知名架构师博客中心
微软架构师网络广播
在线架构技术教程
架构师技术阅读
经典.NET架构启蒙
Architect Journal
国内成功案例
国外成功案例
历史活动
  .NET架构师论坛
  微软活动资讯
当前活动
会员登陆
立即注册
个人信息
会员推荐
RSS 源   Vibro.NET
投递时间 2007年6月4日星期一 23:31
作       者 vibro
主       题 Orcas WCF AJAX + CardSpace 示例的解决方案
整篇文章链接:http://blogs.msdn.com/vbertocci/archive/2007/06/04/the-solution-for-the-orcas-wcf-ajax-cardspace-sample.aspx
       正如我所承诺的那样,这里是一个Visual Studio 解决方案,里面是我上周所写的一编教程的示例,它将告诉你如何将一个CardSpace 令牌从一个Web页面发送到一个AJAX样式的WCF服务中(这是Orcas的新功能)。来看看吧!
>> 查看文章
RSS 源   Vibro.NET
投递时间 2007年5月31日星期四 9:08
作       者 vibro
主       题 A RESTful CardSpace: 在 Orcas 中使用新的 WCF AJAX 服务发送令牌
整篇文章链接:http://blogs.msdn.com/vbertocci/archive/2007/05/30/a-restful-cardspace-sending-tokens-using-the-new-wcf-ajax-services-in-orcas.aspx
类       别 翻译
       简述:这篇文章主要描述了一个示例,它将CardSpace获得的令牌发送到一个使用新的Orcas功能实现的AJAX服务。
       在前面的一些文章中,我曾经发表了一篇关于在Silver中使用CardSpace的指南。在与Workflow团队的Kushal Shah聊天的过程中,他建议我最好也演示一下如何在WCF新的RESTful功能中使用CardSpace:这听上去很符合我的“cardspace+<所选技术>”系列的特点,因此我便开始进行这方面的工作。下面的内容记录了结果。
       绪言
       在实际的进行代码之前,先让我们花一些时间来理解这篇文章要说什么内容。
       .NET framework 3.5,现在还处理beta阶段,它扩展了WCF,添加了很多新的功能,特别是为WEB的开发场景设计了许多新功能。关于这些内容确实有很多话要说,但是今天在我们的主题中,你将会看到开放WCF服务后,它们将非常容易的就可以被WEB页面所访问。实际上,这意味着你可以1)通过HTTP动作(如POST和GET)调用WCF服务并且可以2)以WEB友好的格式来处理消息,例如JSON。简单来说,就是不需要任何代理。你可以用javascript轻松的调用WCF服务:你可以随便从UI上收集一些信息,然后通过AJAX样式(使用XMLHttpRequest或者activeXs Msxml2.XMLHTTP/Microsoft.XMLHTTP)来创建一个WEB请求,最后你可以用返回的结果来更新你的页面的局部内容。这些新的功能可以大大的简化一个网站后端开发的工作,对于这一点也是有着非常深远的影响的:你将可以使用它丰富的模型和宿主功能,构建一个极其强大的服务API,你可以非常轻松的使用它来为Web应用程序开放你的资产。最后,我们不用再为Web服务器的设计模型发愁,我们可以按照内容和服务来进行设计,而不会再设计与维护上将二者混淆。在近几天,你将会在这个blog中多次看到相关的内容。同时,我也向你全心全意的推荐SteveMJustin的blog。
       也就是说:我将会告诉你,在这个场景中你需要什么来使用CardSpace。这并不是一个“合适”的WCF场景:我们的客户端是一个浏览器,因此我们将不会考虑wsHttpBinding 的WS-Security功能以及所有其它的cardspace相关功能的绑定。因为我们主要是处理WEB页面,所以我们可能会使用基于传统Web的CardSpace身份验证架构:我们可能会在AJAX页面前使用它,从而成功的进行身份验证的步骤。但是这也非常的简单 :-) 对于我们的示例来说,我们假设服务的本身需要接收一个来自CardSpace的令牌:这可能在我们使用的服务需要一个令牌的时候发生,这个令牌与我们向网站提供的身份验证所使用的令牌不同(例如,我们使用一个个人的卡片来向网站进行身份验证,但是一些AJAX服务所提供的业务功能需要来自另外的IP的一个特定的卡片才可以)。
       这个示例的演示环境非常简单。你需要Orcas beta 1,并且你可以在Orcas Beta 1版本中找到这个cardspace 示例,以及新的WCF示例(注意:需要一次安装过程)。
项目
       我们的项目将包括一个WCF服务和一个简单的Web 页面,这个页面将会做为客户端。
       为了让演示的场景更加真实,我们把服务宿主在IIS当中:事实上,我们的服务是在PostAjaxService示例中编写的(非常感谢Eugene的帮助)。你将需要创建一个应用程序或者重新使用一个现有的应用程序。
       要注意,因为我们在一个站点中操作CardSpace,所以我们将需要启用HTTPS:如果你安装了它,那么你可以简单的将我们创建的文件部署在相同的目录中,而且你可以直接跳到下个小节(“项目”)。
服务
       编写服务是非常简单的。你可以先编写一个WCF服务库,一个类库,或者其它你喜欢的方式。最后,我们都将编写三个文件:service.cs、service.svc、和web.config。这与你在PostAjaxService示例当中看到的非常的类似,你可以将它修改一下然后使用它。我们所有的cardspace站点的示例都使用一个Helper类来处理令牌:我们将需要向项目当中添加一个TokenProcessor.cs,从CardSpace站点示例的website\CardSpace\App_Code目录。
       下面我们先来看看这三个文件,并且通过我们常用的高亮标记的样式来看。
service.cs
       其中,确实没有什么特殊的代码是我们希望通过AJAX的服务所开放的。它就是一个很平常的WCF服务。
       我们使用了一个using从句来访问一些CardSpace相关的结构,例如ClaimTypes (System.IdentityModel.Claims),以及从TokenProcessor.cs中访问令牌的helper类(Microsoft.IdentityModel.TokenProcessor)。
       黄色的代码声名了一个最小的ServiceContract,其中包含一个方法,它接收一个输入的字符串,并返回另外一个字符串。
       整个服务代码主要就是实现了EchoString这个方法(它使用了所有常见的语句)。
       参数S1表示了令牌字符串,我们将从客户端接收到它。这个令牌字符串实际上是一个加密的XML元素:所以它包含了一些字符是不能通过POST来发送的。因此,我们在将它发送到服务前,首先将令牌的字符串encodeURI:这样将会处理非法的字符,但是这时我将不能解密令牌;很明显,加密/解密的过程被字符串的加密部分弄混了。因此,我决定在发送前将整个令牌字符串转换为base64-编码,然后一切就正常了。天蓝色标记的代码段处理将base64格式的s1解码回它原来的格式。
       绿色标记的代码段将令牌反序列化到一个Token类的实例;这步操作将令牌解密,并显式的检查签名的一致性,但是在实际的应用程序当中,你可以还需要很多显式的检查(比如这个签名是否是你所期望的)。
       粉红色标记的代码段将GivenName中的值提取出来,并将它发送回去。
service.svc
       一个文件能更简单吗?这是一个典型的.svc文件:它使得WCF告诉ASP.NET将在服务中调用哪个类。另外,没有任何我们的RESTful意图。
web.config
       在web.config中,我们将最终看到一些Web动作:
       Services/Service节是很平常的一个节点:我们定义了一个叫做AService.MyService的服务,其中包含一个叫做ajaxEndpoint的端口。好的,几乎和普通的服务一样:绑定的类型是webHttpBinding,它是一个Orcas中的新功能,它允许我们以web的模式来开放服务。
       文件中被方框框住的部分包含了绑定的配置:
  • 灰色标记的代码段显示了启用JSON编码的节点。
  • 绿色标记的代码段增加了输入参数的大小限制。这并不是必需的,但是在Beta1中最好还是添加上这段代码。
  • 天蓝色标记的代码段表示我们的服务将通过HTTPS访问,并且对于处理传输安全性来说,它的语法是与3.0中的使用相同的。要小心了!如果你的服务是通过一个HTTPS连接访问的,那么你就需要添加这个元素,否则调用将会失败。换句话说,你不能只将一个服务从HTTP移动到HTTP应用程序,而相反的:你需要通过config文件告诉WCF在宿主中是否使用传输的安全性。
       青色标记的代码显示了你需要在behavior配置中添加的参数。
       这就是服务器端的代码!将两个*.cs文件编译到一个DLL(一般情况下将会是“service.dll”),并且将它部署到你的Web目录的\bin目录中;然后将service.svc和web.config复制到你的web目录当中。这时服务就可以访问了,你可以去调用它!下面,就让我们来编写一个快速并且直接的客户端来看看它是如何工作的。
客户端
       客户端是一个简单的静态HTML页面,我将把它命名为“Client.HTM”。我们已经知道,在将令牌发送到服务之前,我们将需要一个base64-编码的令牌字符串:在本示例中,我使用了Tyler Akins中现成的base64.js文件(感谢Garrett的提示)。Client.htm非常的大,所以我将它分成两个部分:首先我们浏览纯HTML文件,然后我们再来看Javascript文件。
       在元素中,我们拥有一个普通的CardSpace对象(如方框框住的代码所示)。在需要通过javascript来调用身份选择器的时候,这是一种非常常用的配置:我们的示例就是希望这样,因此我们希望从cardspace获取到一个令牌,并且通过客户端的代码来处理它(并不是单纯的为包含cardspace对象元素的表单执行一个POST,而在服务器端去处理它)。注意,我们不会在客户端做过多的处理,我们只是对令牌字符串进行重新编码,并将它发送到服务器端(更为详细的内容请看下面的javascript部分)。灰色标记的代码显示了Object元素的名称,它将在脚本代码中用来引用元素。
       金黄色标记的代码段显示了base64.js文件的引用。
       然后,我们建立了一个表单(“sampleForm”),它包含了一个非常简单的UI。
       我们使用一个标签关联到GoGetIt函数(黄色标记的代码):将光标放到标签上时将会调用GoGetIt函数,它将会获取来自cardspace的令牌。令牌字符串将会被存储在一个叫做xmlToken(天蓝色标记的代码)的文本框中。
       我们还有另外一个标签,它关联到makeCall函数(绿色标记的代码):将光标放到标签上时将会触发我们的服务,它将发送上一步中获取的令牌字符串。调用的结果(包括错误)将会显示在叫做“result”的input区域中(粉红色标记的代码)。
       让我们来看看GoGetIt函数:
       它对传统的GoGetIt函数做了一些小小的变化。将CardSpace元素赋给一个变量的时候,将会触发身份选择器的显示,然后它会返回一个从用户选择的卡片中获得的令牌所包含的字符串。在我们获得了令牌字符串之后,我们将它进行base64编码,然后我们将它存储在我们的文本框中。注意,我已经选择了这些动作,是为的使这个过程尽量的可见:在一个实际的应用程序当中,你可能只需要在将令牌进行base64编码后直接将它发送,而并不需要在UI上将它显示出来。
       MakeCall 函数就更为复杂一些:
       在方框框住的代码段前面的部分是典型的AJAX相关的代码;我们根据用来展现结果的浏览器的功能来创建了一个xmlHttp,然后我们将确定在它可用后再来计算结果。
       让我们来关注方框中框住的代码。
       第一行创建了URL引用我们的服务,它是一个非常直观的路径:首先是service.svc(灰色标记),它表示了Web服务器上的实际的资源;然后是端口的名称(绿色标记),它是服务项目中的Web.config所定义的;最后是方法的名称(黄色标记),是通过ServiceContract来定义的。
       天蓝色标记的代码显示了我们该如何构建Web请求的消息体:我们只是将base64编码的令牌字符串赋给参数s1。注意:“s1”是我们在service.cs中定义的参数名称,所以在这里我们要使用它。参数名称的错误是一个很常见的问题,而且它可能会困扰你几个小时。
       金黄色标记的代码显示了我们该如何构建请求,并且执行调用:我们建立了一个HTTP动作,我们希望使用(POST),我们将消息头中的content type设置为”application/json”,然后发送。
       右就是这样。只需要将Client.HTM和base64.js复制到虚拟目录当中,然后就没有问题了。
修复权限问题
       由于你的代码需要使用SSL证书来解密到来的令牌,因此你必须要确保应用程序池的启动用户对于证书的私钥有足够的权限。另外,如果你希望使用CardSpace示例中创建的环境,那么你还需要做一些事情。
       你可以这样做:
       1) 找到证书的文件名,使用aforementioned cardspace sample中\bin目录里的FindPrivateKey工具。
       2) 为它设置适当的权限。例如,如果你在Vista系统当中,默认的用户是NETWORKSERVICE:那么设置权限的命令可以这样写:
       cacls C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys\[File Name found in step 1] /E /G NETWORKSERVICE:R
       注意:MSDN上的文档和其它的示例都忽略了“/E”标记,而这样的话你将会替换整个ASCL,有时会发现不可预期的结果(SYSTEM和Administrators将失去对这个文件的访问权):“/E”标记可以解决这个问题。感谢Rafael发现了这个问题 :-)
测试运行
       到了验证的时候了 :-) 让我们打开一个浏览器,然后浏览Client.HTM:
       没有什么稀奇的,但是这正是我们希望看到的(包括表示警告的绿色的地址条)。我们先将光标移动到第一个标签上方:
       普通的CardSpace提示。我们点击发送。
       文本框中现在包含了我们的令牌字符串的base64编码。让我们将光标移动到第二个标签上,并将它发送给Web服务:
       没有问题,正如我们期望的那样,我们得到了givenname的值,这也就证明了服务正确的接收并处理了令牌。
总结
       我们看到了一个简单的示例,告诉我们如何使用Orcas中引入的新的Web功能,将一个WCF服务开放为一个AJAX服务。我们也看到了,如何通过HTTPS来保证服务的安全性,以及如何向它收集并发送CardSpace令牌。如果你还有什么问题,别犹豫赶快问我。
       另外,对于那样比较懒的读者:和上次一样,我将会在之后的BLOG中发布一些解决方案文件…但是我不会马上就做,因为我鼓励你去自己完成它 :-) 祝你愉快!
>> 查看文章
RSS 源   Vibro.NET
投递时间 2007年5月14日星期一 14:03
作       者 vibro
主       题 "缓存"卡片
整篇文章链接:http://blogs.msdn.com/vbertocci/archive/2007/05/13/quot-caching-quot-cards.aspx
在我们谈论cardspace时,缓存是一个我们早晚都要提及的问题。如果我同时或在短时间内,在不同的应用程序之间使用相同的卡片,难道我不能缓存卡片吗?如果在一个特定的应用程序里,我总是使用相同的卡片,那么难道我不能自动化这个过程从而不被提示吗?
这些问题,都是值得去详细回答的。我不会植根于法律去考虑:例如,我可能会说缓存过分扩大了主体的赞成度,因为在那个时间点上,用户的数据将会被泄露。但是,我不会拒绝在身份选择器中实现缓存。在这篇日志当中,我将会告诉大家什么我处理的最好,token junggling:特定格式的缓存不能工作是有原因的,而且这也是我要在这里说的内容之一。这篇文章可以认为是与那篇相当长的文章是一个系列的。
在CardSpace中,一个托管的卡片表示从一个特定的IP获取令牌的能力。如果RP的策略接收来自一个特定IP的令牌,那么主体可以 1)选择代表相应令牌的管理卡片 2)采取一些步骤来让IP识别 3)如果2成功,那么主体将获取到来自IP的令牌,并且在查看它的内容后,他/她决定将它发送到RP。
在这里,需要注意的第一点是,如果我希望缓存一些东西,那么它必须是令牌(the notion of caching a card is, in ws-trust terms, ill-posed)。有很多非常好的原因可以解释为什么有人希望缓存令牌:例如,一个应用程序可能希望与Web服务进行通信,它存在于相同的RP(因此使用相同的X509来保护),但是它拥有与第一个Web服务不同的端口(例如,我可能已经从www.foo.org/ws1获取了我的令牌,而现在我想访问www.foo.org/ws2)。为了解决这种情况,我编写了一个示例。即使在富客户端应用程序当中,CardSpace也没有任何现成的方法来缓存令牌,但是WCF(Cardspace的基础)的扩展性允许我创建一个简单的缓存系统。
现在: 我的缓存系统进行了特意的设计,从而避免在连接相同RP的不同端口时,再去提示主体。因此从事务的角度来看,主体正在处理相同的RP,他/她决定表露相同的业务实体:RP将会的功能使用比一个实现详细更多的端口。但是,我们缓存系统不能在多个RP处工作,原因非常简单:为RP发布的缓存的令牌与目标令牌是不同的。
当我们使用一个托管的卡片来获取一个令牌的时候,我们为我们正在请求的RP加密这个令牌;根据它的审核策略,IP可能知道RP的身份,也可能不知道,但是最终主体返回的令牌是经过加密的,而且只有预期的接收者才可以使用它。基本上,为RP1获取的令牌 & 缓存是不能在RP2处使用的。这就是为什么相同的令牌不能在不同的RP之间重用。
我们可能希望将压力转移到身份选择器上,然后说一个"缓存的托管卡片"是这样实现的:如果成功的为RP1获取到令牌,那么当RP2使用它时,它将简单的重复获取一个合适的令牌的步骤,而不需要主体的交互。再重复一下,我的意思并不是像7条法则那样,但是我也要考虑另外一个实际的问题:为RP1从IP获取一个令牌,需要主体使用一些验证的方式来加密RST,而这种方式可能就不是可缓存的(查看OTP),或者需要主体执行一些显式的步骤(插入一个智能卡,刷一下指纹,等)。
下面附加的图片形象的表示出我所说的内容(下面的记号非常直接:和http://channel9.msdn.com/ShowPost.aspx?PostID=241455是一样的。注意,出于简单的目的,我没有区分公钥和私钥,而是假设E操作员总是使用公钥,S操作员总是使用私钥)。
图中,钻石开关的密钥(用黄色高亮标出)是IP生成的会话密钥:它为第一个RP的密钥加密(矩形的,用天蓝色高亮标出),因此它不能被第二个RP使用(它拥有倒三角开关的密钥)。同样,为了给IP发送一个RST,主体需要圆形的密钥(用绿色高亮标出)。它可能是一个需要pin码的智能卡,OTP或者其它的都 不能被身份选择器缓存(因此验证代码在其它地方)。
附言:我知道上面的内容并不能解决IP总是在线损坏物理卡片的事实。我想身份标识本身对物理卡片的适用性有着一个限制:在在线的模式中,我们拥有加密方法来保证更加的强大,从而使得ID上的全息模式对于假冒,但是只要我们使用卡片作为获得令牌的方法,范围的减小就难以避免。
>> 查看文章
RSS 源   Vibro.NET
投递时间 2007年5月7日星期一 23:02
作       者 vibro
主       题 Silver CardSpace 解决方案示例 & OperationValidation 处理器
整篇文章链接:http://blogs.msdn.com/vbertocci/archive/2007/05/07/the-solution-for-the-silver-cardspace-sample-the-operationvalidation-handler.aspx
在最后一篇相当长的日志里,我写了关于使用CardSpace与Framework 3.5 Beta 1所提供的新的Receive活动功能,我提到了我将会上传最终的解决方案:但是我没有立即上传,那是为了刺激你去真正一步一步的按照教程去做。呵呵,有时候我确实比较坏:-)我现在在这个日志中上传了解决方案:它没有注释,也没有文档,而且非常只是一个粗糙的剪切:这就是我在编写教程的时候所创建的。
关于这个示例。为了使代码保持良好的可读性,我在活动代码中放置了一些逻辑直接访问claim;如果你的活动代码的动作是受claim值影响的,那么这也可能发生在一个实际的应用程序当中。但是,如果您执行一个纯粹的claim验证,那么你最好将claim代码放置在Receive活动的OperationValidation处理函数中(在Visual Studio中浏览Receive活动的属性,你会找到它)。感谢Matt指出这一点。
>> 查看文章
RSS 源   Vibro.NET
投递时间 2007年5月3日星期四 6:05
作       者 vibro
主       题 Silver CardSpace: 使用 Windows CardSpace 加密 Orcas Workflow Services
整篇文章链接:http://blogs.msdn.com/vbertocci/archive/2007/05/02/a-silver-cardspace-securing-orcas-workflow-services-with-windows-cardspace.aspx
简述:这是一个教程,它将一步步的指导你使用Visual Studio 代码号为"Orcas"的Beta 1版本来创建一个Workflow Service。这个教程将会展示如何使用Windows CardSpace来加密服务,如何创建一个客户端应用程序,以及如何从一个工作流活动的代码中访问声名。
在Mix上的Earth-moving news的前几天,我们使用 Visual Studio 代码号为"Orcas"的Beta 1版本建立了另外一个silvery技术:Workflow Services,Silver for friends,是一项激动人心的新技术,它允许开发人员使用WCF和WF来创建面向服务的工作流。按习惯,我想到的第一件事就是如何通过CardSpace为这些新的服务加密:结果是非常简单的,如果我从一个现有的工作流服务项目开始的话,我只需要1/2的内容。但是,Silver技术现在还是最新的:所以我想还是应该写一个完整的教程,这样才是有用的。EDIT:在写完这篇日志几个小时后,我发现已经有了一篇文章WF overlord,这篇文章更加详细了描述了工作流的创建部分:所以我建议你查看Matt的日志,特别是你看到下面的章节遇到障碍的时候。
议程
我们将工作划分成几个步骤:
1. 创建工作流项目
2. 添加并配置Receive活动
3. 在WorkflowServiceHost中宿主工作流
4. 使用CardSpace配置工作流端口
5. 创建一个客户端项目
6. 测试运行
7. 向工作流添加一个声名处理并且然后运行
嗯…这可能会很长。我可能会录制一个屏幕的视频(我无论如何早晚都会做的),但是它不能被搜索,而你又不能快速的预览:因此,我将会花费几个小时来写这篇文章:-)加油吧!
1. 创建工作充项目
这个教程需要一些必备条件:
  • 你需要Visual Studio 代码号为"Orcas"的Beta 1版本;
  • 你应当下载新的WCF示例然后查看one time installation procedure;
  • 教程当中CardSpace的部分供事于常用的adatum-issued Fabrikam证书,可以在这个示例中找到(并安装)。任何其它的证书也可以,你只需要相应地更改config当中的引用即可。
不再费话,言归正传,我们开始。打开Visual Studio ,然后创建一个新的"Sequential Workflow Console Application"项目。
创建一个arbitrary workflow:简单起见,你可以在一个传统的代码活动中放置一些Console.Writeline语句。
至此,像平时一样,点击F5来确保你没有忘记为每一行语句加分号,完成。
2. 添加和配置Receive活动
这里,事情开始渐渐变得有趣起来。让我们假设你希望将你的工作流开放为一个WCF服务。过去("过去"?我们刚刚在几个月以前发布了3.0 :-D I *love* working in Evangelism(作者个人感情强烈,译者不便翻译:-) )),你将不得不编写一大段代码。使用Silver,事情变得更加容易了:起初,你可以在你的工作流中表示服务操作,简单到只需要拖入一个活动,它表示接收一个消息的动作。
在图片的左边,你可以看到在Orcas当中,Workflow工具箱拥有一个额外的活动集合,用红色的矩形围起来了。将一个接收活动拖拽到工作流的第一个活动槽中,如图中所示;然后你可以在新的接收活动中直接迁移你的工作流。
现在,我们直接在工作流中,拥有了一个服务的可视化标记!在下一步中,我们提供关于服务本身的详细信息。设计器指导将我们完成任务:活动右上角非常熟悉的惊叹点提示了下一步操作,它指出"Activity 'receiveActivity1' does not have a service operation specified."。点击该消息,将带我们来到相关的属性页面,如下所示:
继续前进,然后点击ServiceOperationInfo 省略号。我们将会看到下面的对话框:
当然!如果我们希望我们的工作流作为一个服务被调用,我们需要将它映射到一个方法,而这样的一个方法必须属于一个契约。对话框右上角的"Import…"按钮表示我们可以引入现有的契约:这对于实际的应用程序来说很难实现。另外一个按钮"Add Contract"允许我们为我们的工作流创建我们的服务契约。在教程中,我们将创建一个契约,简单起见,我们还是创建一个相当简单的。我们点击"Add Contract"按钮,然后填写对话框,如下图所示:
就像我说的那样,这个契约相当的简单:)其中只有一个操作,"UnleashMyAppLogic",它没有参数也没有返回值(我保证后面的一些日志将会详细的说明如何处理I/O)。
当我们返回到对话框时,我们发现receiveActivity符号现在被标识为它规范的操作名称。很好,这将帮助我们理解工作流做什么。
我们仍然拥有一系列任务来完成这个步骤:
  • 在属性页中,你可以看到我用红色高亮标出了CanCreateInstance属性:这个属性表示在运行时我们映射的操作是否拥有创建一个工作流实例的权限,或者如果与一个现有的工作流实例关联时它是否可以工作。在我们的示例中,这个操作将会实际开始工作流:我们当然希望它可以创建一个实例,所以我们将这个属性设置为true;
  • 在解决方案的引用中,我用绿色高亮标出了一个程序集,SMDiagnostics;它被误添加了(这是beta 1的bug)。你需要将这个引用删除,否则它将不会通过编辑。
3. 在WorkflowServiceHost中宿主工作流
现在,我们修改我们的工作流,让它成为一个服务,我们需要提供一个充分的宿主环境。
Silver 提供了一个新的宿主类,WorkflowServiceHost,它是一个介于WorkflowRuntime 和ServiceHost之间的交叉体。你可以通过一个表示工作流服务的工作流类(如我们上面的步骤中所创建的)来使用WorkflowServiceHost ,它将会为你处理端口的创建并处理请求。:-)
你可以打开Program.cs的代码,然后使用下面的代码替换Main函数:
用黄色高亮标识出的代码,使用我们的工作流实例化了一个WorkflowServiceHost类(使用工作流类的默认类名,Workflow1)。用浅蓝色高亮标识的代码显示了WorkflowServiceHost如何像ServiceHost那样工作的。WorkflowServiceHost位于System.ServiceModel命名空间当中,所以你还需要添加适当的using语句。
编译项目,但是我们还没有完成主要工作:我们需要执行下面的步骤,然后才能接收进来的请求。
4. 使用CardSpace配置工作流端口
不要让这个步骤的名字把你带入歧途:你需要配置工作流服务端口,CardSpace或者不配置CardSpace。这里,我们只用一个绑定,它将会涉及图中的CardSpace。
我们要做的非常简单:我们需要向项目中添加一个配置文件,然后我们需要用它来定义我们希望开放的服务与端口的详细内容。
右击项目,然后添加一个叫做"Application Configuration File"的项。然后,我们将下面的服务段粘贴到该配置文件当中:
黄色的代码用来定义服务和端口。服务的名字是与实现服务的工作流的类名是匹配的,SilverCardSpaceWorkflowService.Workflow1;baseAddress表示客户端将使用这个地址来调用服务;contract当中是我们在上面第一步中的工作流里定义的契约。所有蓝色的部分定义了通过电子证书来确定服务的必须的安全信息,并且指示客户端服从wsHttpBinding。通过binding和behavior配置,如下所示,这些设置将诱使客户端每次调用这个服务的时候都要使用cardspace。
这确实非常简单,在这个config当中并没有建议我们不去使用一个正常的WCF服务。
注意,Silver实际上使用它自己的绑定,wsHttpContextBinding,这是启用许多重要功能的关键,比如持久服务,到正确工作流实例调用的自动处理等等(你可以看到一个上面代码的例子,在注释部分)。我强烈建议你去学习示例,而且去看一看Matt的blog,从而学习有关上面内容的更多信息。在这里我们使用wsHttpBinding,因为我们希望使用cardspace。
5. 创建一个客户端项目
现在,我们开始运行工作流服务。点击Control+F5(启动不调试),然后你将会看到命令行版本的Dr.Fraiser。
如果你使用浏览器去访问服务的地址(你可以从config文件中复制:http://localhost:8888/ServiceHost/Workflow1.svc),那么你将会看到的元数据页面。
工作流的客户端不需要任何配置,只需要一个到我们开放的方法的调用就可以了:通过"添加服务引用"的功能,我们立即就可以使用它,所以我们将保持这个实例运行:我们需要它来获取必要的元数据。
在相同的解决方案下创建一个新的命令行项目:
右击新创建项目的引用目录,然后选择"添加服务引用"。你的剪贴板中是不是还留着服务的地址着?好的,我们需要:将它粘贴到添加服务引用对话框中,visual studio将查询服务宿主的运行实例,然后引用它。
这样就可以了,它将会自动创建一个正确的的app.config。
这时,你只需要从Program.cs中的Main里调用服务即可。
用黄色高亮标出的代码,将实例化一个代理,并调用它。
用蓝色高亮标出的代码用来关闭测试证书的取消检查:通常你都会希望将这个检查关闭,这只是测试用途。
6. 测试运行
我所描述的这个过程看上去很长,但是它实际上操作起来非常快速。
我们现在可以最终测试我们的运行了:将解决方案设置为多启动项目,将两个项目都设置为"启动",然后我们就可以开始测试了!点击F5然后我们来看。
在后面,我们有一个工作流服务宿主过程,在前面是客户端。在客户端命令行中点击回车键。
因为我们对工作流服务进行了强制绑定,所以我们将看到非常熟悉的cardspace UI!让我们发送card,然后查看调用是否正常:
没问题。我们可以在服务控制台中看到,一切都按预期的那样。
我们可以正式的欢庆:我们使用cardspace成功的调用了一个工作流服务!!!
7. 向工作流中添加声名处理然后重新运行
实际上,现在工作流正在使用从cardspace获取的令牌开始工作。从工作流活动的代码当中访问令牌是非常简单的,你可以使用与传统的WCF服务相同的机制。你可以修改Workflow1.cs文件当中的活动源代码,如下所示:
黄色高亮标出的代码处理AuthorizationContext的获取,在这里我们可以访问claim的值以及与调用是如何被加密的其它详细信息。注意,编译器不会识别上面的代码,直到你添加了必须的"using":幸运的是,Visual Studio智能标记使得操作快速简便。
重新运行示例,你将会看到我们实际访问的claim:
注意红色方框高亮标出的区域里,我们可以看到进来的PPID。完成!
结论
我们将一个工作流开放为一个服务,而无需编写过多的代码;我们添加了cardspace的支持,并且只需要添加一些配置,与我们在纯WCF+cardspace救命中使用的一样。为了照顾一些手脚不太勤快的人,我将会为这个教程附加一个ZIP。如果有什么问题,请直接告诉我。