WCF分布式开发必备知识(4):Web Service

简介:
     今天继续我们的 WCF分布式开发必备知识系列文章的第4节:Web Service.前3节我们分别介绍了MSMQ消息队列\.Net Remoting\Enterprise Services三个相关的技术.并且给详细注释的代码实现例子.先介绍一下本节的文章组织结构,首先还是介绍1.Web Service的基本概念2.优势和缺点3.使用Web Service的场合4.安全问题5.实现代码部分最后是总结.初学者就当入门资料,高手就当温习,也欢迎提出意见.
     那现在我们就开始今天的学习,网上关于 Web Service的资料很多,但是也很杂乱,混淆了基本概念.
      1.Web Service的基本概念
       什么是Web Services?Web Services 是设计支持支持机器与机器的通过网络互操作的一种软件系统(W3C的定义).是一组可以通过网络调用的应用程序API.Web Services 是应用程序组件 , 使用开放协议进行通信 ,独立的(self-contained)并可自我描述 ,可通过使用UDDI来发现 ,可被其他应用程序使用的功能.
     Web services 平台主要涉及到XML \SOAP\WSDL\UDDI四个主要元素.我们在这里简要做下介绍.
     (1)XML :XML是EXtensible Markup Language的缩写,XML是一种类似于HTML的标记语言,XML是用来描述数据的,XML的标记不是在XML中预定义的,你必须定义自己的标记 XML使用文档类型定义(DTD)或者模式(Schema)来描述数据 ,XML使用DTD或者Schema后就是自描述的语言.
     (2)SOAP :SOAP(Simple Object Access Protocol)简单对象访问协议是在分散或分布式的环境中交换信息的简单的协议,是一个基于XML的协议。它包括四个部分:SOAP封装(envelop),封装定义了一个描述消息中的内容是什么,是谁发送的,谁应当接受并处理它以及如何处理它们的框架;SOAP编码规则(encoding rules),用于表示应用程序需要使用的数据类型的实例; SOAP RPC表示(RPC representation),表示远程过程调用和应答的协定;SOAP绑定(binding),使用底层协议交换信息。 
     (3)WSDL: Web services 描述语言,它的主要构成要素有五个.Types: 定义WSDL定义中所用到的数据类型,即XML Schema Types;Message : 对一组消息的输入和输出参数的定义;portType : 定义Web服务的操作;Binding :描述特定服务接口的协议、数据格式、安全性和其它属性.Services : 制定特定服务的URL和提供的调用接口,包含一组端口元素.  这样Web services 就实现了自我描述.
     (4) UDDI :Universal Description Discovery and Integration即统一描述、发现和集成协议。UDDI同时也是Web服务集成的一个体系框架。它包含了服务描述与发现的标准规范。UDDI规范利用了W3C和Internet工程任务组织(IETF)的很多标准作为其实现基础,比如扩展标注语言(XML),HTTP和域名服务(DNS)这些协议。有了它我们的Web services 就可以注册到UDDI中心.供其客户查找使用.
     Web services 一般分为4类:
(1)面向业务的服务(Business-Oriented Web Service): 该类服务针对的是那些面向企业应用服务;
(2)面向客户的服务(Consumer-Oriented Web Service): 此类服务针对的是那些原先的B2C的网站的改造,比如我们完全就可以在个人理财桌面系统中集成(调用)Internet上的股票价格查询Web服务、机票预定Web服务等,使得个人理财应用的自动化程度更高。
(3)面向设备的服务(Device-Oriented Web Service): 此类服务的使用终端一般是手持设备和日用家电,比如Palm、PocketPC、手机等。。
(4)面向系统的服务(System-Oriented Web Service): 一些传统意义上的系统服务,比如用户权限认证,系统监控等,譬如跨国企业的所有在线服务可以使用同一个用户权限认证Web服务。
     2.Web Service优势和缺点
    我们先来了解以前平台的缺点.中间件平台(RMI, Jini, CORBA, DCOM 等等)提供了强大的服务实现手段,但是,这些系统有一个共同的缺陷,那就是它们无法扩展到互联网上:它们要求服务客户端与系统提供的服务本身之间必须进行紧密耦合,即要求一个同类基本结构。不支持跨平台的信息交换.而对比后我们就发现,  Web Service 的很显然具有以下优点:
(1)跨平台:WebService完全基于XML(可扩展标记语言)、XSD(XMLSchema)等独立于平台、独立于软件供应商的标准;
(2)自描述:Web Service 使用WSDL标准语言进行自我描述,包括服务的方法\参数\类型\返回值等相关的完备信息.
(3)模块化:Web Service 是应用程序组件,我们可以使用任何开发平台来开发,并且按照模块进行封装.
(4)跨放火墙:Web Service 使用http协议进行通信,可以穿越防火墙.
    Web Service 的缺点也很明显:
(1)效率低下,不适合做单应用系统的开发.
(2)安全问题,Web Service的没有自身的安全机制,必须借助http协议或IIS等宿主程序实现信息安全加密
     3.Web Service使用的场合
     那么什么时候应该使用Web Service,从上面的总结我们可以看出.使用Web Service能够带来利益的情况.
(1)跨防火墙的通信
(2)应用程序集成,主要是指企业应用系统的集成.
(3)B2B的集成,主要是指电子商务平台的集成.
(4)软件和数据重用,软件重用是一个很大的主题,重用的形式很多,重用的程度有大有小。最基本的形式是源代码模块或者类一级的重用,另一种形式是二进制形式的组件重用。
     有一些情况,不适合使用WebService。
  (1)单机应用程序
  单机应用程序如office等,可以直接调用系统WindowsAPI\COM进行编程,实现功能效率更高.
  (2)局域网的同构应用程序
      例如在局域网里,使用COM+和.NET Remoting进行通信,会获得更高的效率.我们不需要使用WebService.
    4.Web Service安全问题
     安全问题是开发和部署Web service涉及最多的问题,主要还是防止重要信息的泄露.包括非法请求和恶意攻击.网络常见的安全问题Web service都会面临.
     Web service的部署方式一般包括3种:
(1)IIS托管.这个最简单,直接借助IIS,发布方式类网站发布.
(2)Console.可以驻留在控制台程序中.
(3)Windows Service.驻留在系统服务中.
     最常见的就是Web service通过IIS托管发布,这个方式好处是它可以使用所有的ASP.Net的认证授权机制。
     Web service处在表示层和业务逻辑层之间.当然它可以直接地与数据库交互. 简单的验证办法就是调用方法里实现对请求的合法性的判断.通过验证我们就执行Web Method,返回用户数据简单的办法是使用System.Web.Services.Protocols.SoapHeader的类。来传递客户票据到服务器进行验证.下我们我们将实现简单的Web service和验证机制.
    通过IIS部署的Web Service,安全也可以通过iis网站属性里设置。包括
(1)身份验证和属性控制,可以集成Windows验证、域服务器验证、.Net Passport验证。如下图。
(2)IP域名限制,只允许特定的ip或者域内机器访问,对非法的请求进行过滤,如下图。
(3)安全通信设置,用户可以启用Web服务器证书,采用SSL对网络传递的信息进行加密,来保证Web Service的安全,如下图。
(具体实现可以baidu)
 
   5.Web Service开发
     Web Service开发十分简单,利用Visual Studio 2005\8都有清楚的向导,在新建web项目里,选择Web Service服务即可.如图.
     我们今天的开发流程主要包括一下4步:
1).创建一个类继承自SOAPheader,来接收 SOAP header里的消息。
2).添加一个方法在服务端Web service类和客户端(添加引用会自动生成服务端类的代理)。
3).添加属性SoapHeaderAttribute到 Web service类和客户端代理服务类的方法上。
4).可以在客户端访问代理类设置SOAPheader的票据值,服务端判断客户端SOAPheader里的票据值。根据验证结果是否相应调用。
     首先定义一下自己的MySOAPheader类,继承自SOAPheader.和web service一个项目.主要是传递用户的票据,自己可以实现更复杂的定义,包括用户名称和密码等,这里只做了简单的实现,为了demo.代码如下:
InBlock.gif 1using System; 
InBlock.gif 2using System.Data; 
InBlock.gif 3using System.Configuration; 
InBlock.gif 4using System.Web; 
InBlock.gif 5using System.Web.Security; 
InBlock.gif 6using System.Web.UI; 
InBlock.gif 7using System.Web.UI.WebControls; 
InBlock.gif 8using System.Web.UI.WebControls.WebParts; 
InBlock.gif 9using System.Web.UI.HtmlControls; 
InBlock.gif10using System.Web.Services; 
InBlock.gif11using System.Web.Services.Protocols; //SoapHeader处于此命名空间 
InBlock.gif12/** //// <summary> 
InBlock.gif13 /// Coded By Frank Xu Lei 2/17/2009 http://www.cnblogs.com/frank_xl/ 
InBlock.gif14 /// MySoapHeader 定义用来传递来自用户的 Soap消息的Soap Header信息 
InBlock.gif15 /// </summary> 
InBlock.gif16public  class MySoapHeader : SoapHeader //用户自定义SoapHeader类必须继承于SoapHeader 
InBlock.gif17{ 
InBlock.gif18         //属性,存储用户票据 
InBlock.gif19         private  string _token; 
InBlock.gif20         //构造函数 
InBlock.gif21         public MySoapHeader() 
InBlock.gif22        { 
InBlock.gif23                 // 
InBlock.gif24                 // TODO: Add constructor logic here 
InBlock.gif25                 // 
InBlock.gif26        } 
InBlock.gif27         //重载构造函数 
InBlock.gif28         public MySoapHeader( string sToken) 
InBlock.gif29        { 
InBlock.gif30                 this._token = sToken; 
InBlock.gif31 
InBlock.gif32        } 
InBlock.gif33         //属性访问器 
InBlock.gif34         public  string Token 
InBlock.gif35        { 
InBlock.gif36                get {  return  this._token; } 
InBlock.gif37 
InBlock.gif38                set {  this._token = value; } 
InBlock.gif39        } 
InBlock.gif40}
     用户自定义SoapHeader类必须继承于SoapHeader.
     其次.另外一个实现用户信息验证的类,独立出来,主要是为了说明验证的框架,用户可以在此实现访问数据库验证等更复杂的实现.具体代码如下
 1 using  System;
 2 using  System.Collections.Generic;
 3 using  System.Text;
 4 namespace  WebServiceUserValidation
 5 ExpandedBlockStart.gif {
 6    public class UserValidation
 7ExpandedSubBlockStart.gif    {
 8        public UserValidation()
 9ExpandedSubBlockStart.gif        {
10        }

11        //定义一个方法,判断用户名和密码是否有效
12        public static bool IsUserLegal(string sName,string sPsw)
13ExpandedSubBlockStart.gif        {
14            //用户可以访问数据库进行用户和密码的验证
15            //这里为了说明用户密码的校验,仅仅作了简单的比较,不作实现
16            string psw ="FrankXuLei";
17            if (string.Equals(psw, sPsw))
18ExpandedSubBlockStart.gif            {
19                return true;
20            }

21            else 
22ExpandedSubBlockStart.gif            {
23                return false;
24            }

25        }

26        //定义一个方法,判断用户票据是否有效
27        public static bool IsUserLegal(string sToken)
28ExpandedSubBlockStart.gif        {
29            //用户可以访问数据库进行用户票据验证
30            //这里为了说明用户票据的校验,仅仅作了简单的比较,不作实现
31            string psw = "FrankXuLei";
32            if (string.Equals(psw, sToken))
33ExpandedSubBlockStart.gif            {
34                return true;
35            }

36            else
37ExpandedSubBlockStart.gif            {
38                return false;
39            }

40        }

41    }

42}

43
     用户可以访问数据库进行用户和密码的验证,这里为了说明用户密码的校验,仅仅作了简单的比较,不作实现.
     再次定义Web Service服务类.代码如下,添加刚才实现的 UserValidation类库.要在服务里使用.代码如下:
ExpandedBlockStart.gif
 1using System;
 2using System.Web;
 3using System.Web.Services;
 4using System.Web.Services.Protocols;
 5using WebServiceUserValidation;
 6//定义WebService的命名空间,为避免重复,通常设置为URL地址
 7[WebService(Namespace = "http://www.cnblogs.com/frank_xl/")]
 8//Coded By Frank Xu Lei,2/17/2009
 9[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
10public class FrankXuWebService : System.Web.Services.WebService
11ExpandedBlockStart.gif{
12    //存储包含用户票据Soap Header信息的属性字段,MySoapHeader继承自SoapHeader,我们在服务端定义实现
13    public MySoapHeader _authenticationToken;
14    private const string _token = "FrankXuLei";//长属性字段,存储我们服务器端的票据,
15    //
16    public FrankXuWebService()
17ExpandedSubBlockStart.gif    {
18
19        //Uncomment the following line if using designed components 
20        //InitializeComponent(); 
21    }

22    //定义SoapHeader传递的方向,
23    //SoapHeaderDirection.In;只发送SoapHeader到服务端
24    //SoapHeaderDirection.Out;只发送SoapHeader到客户端
25    //SoapHeaderDirection.InOut;发送SoapHeader到服务端和客户端
26    //SoapHeaderDirection.Fault;服务端方法异常的话,会发送异常信息到客户端
27    [SoapHeader("_authenticationToken")]
28    //设置方法SoapHeader属性,用于WebService的方法处理Soap Header消息
29    //"_authenticationToken"就是定义的FrankXuWebService类的私有属性名称,
30    [WebMethod(EnableSession=false)]
31    public string HelloFrank() 
32ExpandedSubBlockStart.gif    {
33
34        //要想在浏览器直接使用Invoke测试服务,这个用户票据代码要注销,不然会无法调用
35        if (_authenticationToken != null && UserValidation.IsUserLegal(_authenticationToken.Token ))//验证票据的值是否正确,
36ExpandedSubBlockStart.gif        {
37            return "Hello Frank,WebMethod is called sucessfully";
38        }

39        else
40ExpandedSubBlockStart.gif        {
41            throw new Exception("Authentication Failed");
42        }

43    }

44    
45}

46
    定义SoapHeader传递的方向,SoapHeaderDirection.In;只发送SoapHeader到服务端,SoapHeaderDirection.Out;只发送SoapHeader到客户端,SoapHeaderDirection.InOut;发送SoapHeader到服务端和客户端SoapHeaderDirection.Fault;服务端方法异常的话,会发送异常信息到客户端.
    最后建立控制台客户端,添加本地项目的web service引用,会生成一个代理类.这个负责和服务器段的交互.具体代码:
 
 
 
ExpandedBlockStart.gif
 1
 2namespace ConsoleWebServiceClient
 3ExpandedBlockStart.gif{
 4    class Program
 5ExpandedSubBlockStart.gif    {
 6        static void Main(string[] args)
 7ExpandedSubBlockStart.gif        {
 8            
 9            //实例化一个简单对象访问协议的头,SoapHeader
10            localhost.MySoapHeader mySoapHeader = new ConsoleWebServiceClient.localhost.MySoapHeader();
11            //对象设置客户端知道的票据的值
12            mySoapHeader.Token = "FrankXuLei";
13            string sResult = string.Empty;
14            localhost.FrankXuWebService frankXuWebService = null;
15            try
16ExpandedSubBlockStart.gif            {
17                //实例化一个客户端引用Web服务的类
18                frankXuWebService = new ConsoleWebServiceClient.localhost.FrankXuWebService();
19                //设置Web服务的SoapHeader
20                frankXuWebService.MySoapHeaderValue = mySoapHeader;
21                //调用Web服务的HelloWorld()方法。
22                sResult = frankXuWebService.HelloFrank();
23                //输出结果
24                Console.WriteLine(sResult);
25            }

26            catch (Exception ex)
27ExpandedSubBlockStart.gif            {
28                //
29                Console.WriteLine("Call WebService is failed");
30                throw ex;
31            }

32            finally
33ExpandedSubBlockStart.gif            {
34                //释放托管资源
35                if (frankXuWebService != null)
36                    frankXuWebService.Dispose();
37            }

38            
39            //调试
40            Console.WriteLine("Press any key to continue"); 
41            Console.ReadLine(); 
42
43        }

44    }

45}

46
    实例化一个客户端引用Web服务的代理类, frankXuWebService = new ConsoleWebServiceClient.localhost.FrankXuWebService();设置Web服务的SoapHeader            frankXuWebService.MySoapHeaderValue = mySoapHeader;调用Web服务的HelloWorld()方法。 sResult = frankXuWebService.HelloFrank();输出结果:如下图:
    上图显示了调用结果的成功,当客户端传递的票据正确的时候,服务方法会正确执行.返回客户端结果.否则执行将失败.
6.总结.
     本文基本上介绍了 Web Service的基本概念\优势和缺点\使用 Web Service的场合\安全问题\实现代码部分,如何创建一个web服务和使用简单的认证机制SoapHeader来获取和验证用户请求的合法性.这个只是解决服务器端验证的问题.但是没有实现数据传递的加密.用户的密码信息的泄露也是 Web Service的安全隐患.另外使用SSL(是Secure Sockets Layer通讯协议)用来保护传输中的资料,把在网页以及服务器之间的数据传输加密起来,在利用iis的安全认证机制,结合几重措施,才能很好地保护 Web Service的安全.本节的代码下载 /Files/frank_xl/WebService.rar.WSE也可以实现Web Service的通信安全.由于其涉及知识交多,篇幅限制不在这里多详细叙述.网上的资料不多,大部分是英文,我打算专门补充一个WSE安全开发系列文章,与大家进行学习.有兴趣的朋友可以继续关注.
     另外本文也是这个系列的最后一节,基本上对之前的分布式开发的几个技术都做了回顾.这个也是对我们学习WCF分布式开发打了一个很好的基础.开发的很多知识都有相似之处.我们博学才能融会贯通.才能更好地学习WCF.希望此系列文章对大家有所帮助.谢谢!~~



 本文转自 frankxulei 51CTO博客,原文链接:http://blog.51cto.com/frankxulei/320397,如需转载请自行联系原作者


相关文章
|
11天前
|
数据库 开发者 Python
web应用开发
【9月更文挑战第1天】web应用开发
27 1
|
8天前
|
数据采集 Java 数据挖掘
Java IO异常处理:在Web爬虫开发中的实践
Java IO异常处理:在Web爬虫开发中的实践
|
9天前
|
前端开发 JavaScript 持续交付
Web应用开发的方法
Web应用开发的方法
11 1
|
9天前
|
前端开发 JavaScript 持续交付
web应用开发
web应用开发
19 1
|
11天前
|
Web App开发 数据采集 iOS开发
「Python+Dash快速web应用开发」
这是「Python+Dash快速web应用开发」系列教程的第十六期,本期将介绍如何在Dash应用中实现多页面路由功能。通过使用`Location()`组件监听URL变化,并结合回调函数动态渲染不同页面内容,使应用更加模块化和易用。教程包括基础用法、页面重定向及无缝跳转等技巧,并通过实例演示如何构建个人博客网站。
22 2
WK
|
8天前
|
数据采集 API 开发者
很少有人用python开发web???
Python 是一种流行且广泛使用的编程语言,尤其在 Web 开发领域。它凭借简洁的语法、丰富的框架(如 Django 和 Flask)、强大的库支持及活跃的社区,成为许多开发者和企业的首选。Python 的易学性、高效性及广泛的应用场景(包括 Web API、微服务和数据分析等)使其在 Web 开发中占据重要地位,并将持续发挥更大作用。
WK
29 0
|
12天前
|
开发者 云计算 数据库
从桌面跃升至云端的华丽转身:深入解析如何运用WinForms与Azure的强大组合,解锁传统应用向现代化分布式系统演变的秘密,实现性能与安全性的双重飞跃——你不可不知的开发新模式
【8月更文挑战第31天】在数字化转型浪潮中,传统桌面应用面临新挑战。本文探讨如何融合Windows Forms(WinForms)与Microsoft Azure,助力应用向云端转型。通过Azure的虚拟机、容器及无服务器计算,可轻松解决性能瓶颈,满足全球用户需求。文中还提供了连接Azure数据库的示例代码,并介绍了集成Azure Storage和Functions的方法。尽管存在安全性、网络延迟及成本等问题,但合理设计架构可有效应对,帮助开发者构建高效可靠的现代应用。
13 0
|
12天前
|
数据库 开发者 Java
数据战争:Hibernate的乐观与悲观锁之争,谁将主宰并发控制的王座?
【8月更文挑战第31天】在软件开发中,数据一致性至关重要,尤其是在多用户并发访问环境下。Hibernate 作为 Java 社区常用的 ORM 框架,提供了乐观锁和悲观锁机制来处理并发问题。乐观锁假设数据不易冲突,通过版本号字段 (`@Version`) 实现;悲观锁则假定数据易冲突,在读取时即加锁。选择哪种锁取决于具体场景:乐观锁适合读多写少的情况,减少锁开销;悲观锁适合写操作频繁的场景,避免数据冲突。正确应用这些机制可提升应用程序的健壮性和效率。
22 0
|
12天前
|
Java 测试技术 容器
从零到英雄:Struts 2 最佳实践——你的Web应用开发超级变身指南!
【8月更文挑战第31天】《Struts 2 最佳实践:从设计到部署的全流程指南》深入介绍如何利用 Struts 2 框架从项目设计到部署的全流程。从初始化配置到采用 MVC 设计模式,再到性能优化与测试,本书详细讲解了如何构建高效、稳定的 Web 应用。通过最佳实践和代码示例,帮助读者掌握 Struts 2 的核心功能,并确保应用的安全性和可维护性。无论是在项目初期还是后期运维,本书都是不可或缺的参考指南。
22 0
|
12天前
|
前端开发 开发者 安全
JSF面向对象设计,让你轻松应对复杂业务需求,Web应用开发不再难!
【8月更文挑战第31天】在现代Web应用开发中,JSF(JavaServer Faces)框架凭借其强大的面向对象编程能力广泛应用于数据绑定和事件处理。数据绑定机制使前端与后端模型解耦,提高代码维护性和类型安全性;事件处理机制则增强了应用灵活性并进一步降低耦合度。本文通过示例代码展示了JSF的这些特性及其优势,帮助开发者更好地利用JSF构建高效、灵活的Web应用。然而,JSF也存在组件库较小和学习成本较高的局限,需根据具体需求权衡使用。
23 0