今天继续我们的
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 就实现了自我描述.
(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。
(2)应用程序集成,主要是指企业应用系统的集成.
(3)B2B的集成,主要是指电子商务平台的集成.
(4)软件和数据重用,软件重用是一个很大的主题,重用的形式很多,重用的程度有大有小。最基本的形式是源代码模块或者类一级的重用,另一种形式是二进制形式的组件重用。
有一些情况,不适合使用WebService。
(1)单机应用程序
单机应用程序如office等,可以直接调用系统WindowsAPI\COM进行编程,实现功能效率更高.
(2)局域网的同构应用程序
例如在局域网里,使用COM+和.NET Remoting进行通信,会获得更高的效率.我们不需要使用WebService.
例如在局域网里,使用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通过IIS托管发布,这个方式好处是它可以使用所有的ASP.Net的认证授权机制。
Web service处在表示层和业务逻辑层之间.当然它可以直接地与数据库交互.
简单的验证办法就是调用方法里实现对请求的合法性的判断.通过验证我们就执行Web Method,返回用户数据简单的办法是使用System.Web.Services.Protocols.SoapHeader的类。来传递客户票据到服务器进行验证.下我们我们将实现简单的Web service和验证机制.
通过IIS部署的Web Service,安全也可以通过iis网站属性里设置。包括
(1)身份验证和属性控制,可以集成Windows验证、域服务器验证、.Net Passport验证。如下图。
(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.代码如下:
1using System;
2using System.Data;
3using System.Configuration;
4using System.Web;
5using System.Web.Security;
6using System.Web.UI;
7using System.Web.UI.WebControls;
8using System.Web.UI.WebControls.WebParts;
9using System.Web.UI.HtmlControls;
10using System.Web.Services;
11using System.Web.Services.Protocols; //SoapHeader处于此命名空间
12/** //// <summary>
13 /// Coded By Frank Xu Lei 2/17/2009 http://www.cnblogs.com/frank_xl/
14 /// MySoapHeader 定义用来传递来自用户的 Soap消息的Soap Header信息
15 /// </summary>
16public class MySoapHeader : SoapHeader //用户自定义SoapHeader类必须继承于SoapHeader
17{
18 //属性,存储用户票据
19 private string _token;
20 //构造函数
21 public MySoapHeader()
22 {
23 //
24 // TODO: Add constructor logic here
25 //
26 }
27 //重载构造函数
28 public MySoapHeader( string sToken)
29 {
30 this._token = sToken;
31
32 }
33 //属性访问器
34 public string Token
35 {
36 get { return this._token; }
37
38 set { this._token = value; }
39 }
40}
2using System.Data;
3using System.Configuration;
4using System.Web;
5using System.Web.Security;
6using System.Web.UI;
7using System.Web.UI.WebControls;
8using System.Web.UI.WebControls.WebParts;
9using System.Web.UI.HtmlControls;
10using System.Web.Services;
11using System.Web.Services.Protocols; //SoapHeader处于此命名空间
12/** //// <summary>
13 /// Coded By Frank Xu Lei 2/17/2009 http://www.cnblogs.com/frank_xl/
14 /// MySoapHeader 定义用来传递来自用户的 Soap消息的Soap Header信息
15 /// </summary>
16public class MySoapHeader : SoapHeader //用户自定义SoapHeader类必须继承于SoapHeader
17{
18 //属性,存储用户票据
19 private string _token;
20 //构造函数
21 public MySoapHeader()
22 {
23 //
24 // TODO: Add constructor logic here
25 //
26 }
27 //重载构造函数
28 public MySoapHeader( string sToken)
29 {
30 this._token = sToken;
31
32 }
33 //属性访问器
34 public string Token
35 {
36 get { return this._token; }
37
38 set { this._token = value; }
39 }
40}
用户自定义SoapHeader类必须继承于SoapHeader.
其次.另外一个实现用户信息验证的类,独立出来,主要是为了说明验证的框架,用户可以在此实现访问数据库验证等更复杂的实现.具体代码如下
1
using
System;
2 using System.Collections.Generic;
3 using System.Text;
4 namespace WebServiceUserValidation
5 {
6 public class UserValidation
7 {
8 public UserValidation()
9 {
10 }
11 //定义一个方法,判断用户名和密码是否有效
12 public static bool IsUserLegal(string sName,string sPsw)
13 {
14 //用户可以访问数据库进行用户和密码的验证
15 //这里为了说明用户密码的校验,仅仅作了简单的比较,不作实现
16 string psw ="FrankXuLei";
17 if (string.Equals(psw, sPsw))
18 {
19 return true;
20 }
21 else
22 {
23 return false;
24 }
25 }
26 //定义一个方法,判断用户票据是否有效
27 public static bool IsUserLegal(string sToken)
28 {
29 //用户可以访问数据库进行用户票据验证
30 //这里为了说明用户票据的校验,仅仅作了简单的比较,不作实现
31 string psw = "FrankXuLei";
32 if (string.Equals(psw, sToken))
33 {
34 return true;
35 }
36 else
37 {
38 return false;
39 }
40 }
41 }
42}
43
2 using System.Collections.Generic;
3 using System.Text;
4 namespace WebServiceUserValidation
5 {
6 public class UserValidation
7 {
8 public UserValidation()
9 {
10 }
11 //定义一个方法,判断用户名和密码是否有效
12 public static bool IsUserLegal(string sName,string sPsw)
13 {
14 //用户可以访问数据库进行用户和密码的验证
15 //这里为了说明用户密码的校验,仅仅作了简单的比较,不作实现
16 string psw ="FrankXuLei";
17 if (string.Equals(psw, sPsw))
18 {
19 return true;
20 }
21 else
22 {
23 return false;
24 }
25 }
26 //定义一个方法,判断用户票据是否有效
27 public static bool IsUserLegal(string sToken)
28 {
29 //用户可以访问数据库进行用户票据验证
30 //这里为了说明用户票据的校验,仅仅作了简单的比较,不作实现
31 string psw = "FrankXuLei";
32 if (string.Equals(psw, sToken))
33 {
34 return true;
35 }
36 else
37 {
38 return false;
39 }
40 }
41 }
42}
43
用户可以访问数据库进行用户和密码的验证,这里为了说明用户密码的校验,仅仅作了简单的比较,不作实现.
再次定义Web Service服务类.代码如下,添加刚才实现的
UserValidation类库.要在服务里使用.代码如下:
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
11{
12 //存储包含用户票据Soap Header信息的属性字段,MySoapHeader继承自SoapHeader,我们在服务端定义实现
13 public MySoapHeader _authenticationToken;
14 private const string _token = "FrankXuLei";//长属性字段,存储我们服务器端的票据,
15 //
16 public FrankXuWebService()
17 {
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()
32 {
33
34 //要想在浏览器直接使用Invoke测试服务,这个用户票据代码要注销,不然会无法调用
35 if (_authenticationToken != null && UserValidation.IsUserLegal(_authenticationToken.Token ))//验证票据的值是否正确,
36 {
37 return "Hello Frank,WebMethod is called sucessfully";
38 }
39 else
40 {
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引用,会生成一个代理类.这个负责和服务器段的交互.具体代码:
1
2namespace ConsoleWebServiceClient
3{
4 class Program
5 {
6 static void Main(string[] args)
7 {
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
16 {
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)
27 {
28 //
29 Console.WriteLine("Call WebService is failed");
30 throw ex;
31 }
32 finally
33 {
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,如需转载请自行联系原作者