Web Service 安全扩展(SecurityExtension ) vme

  问题

关于 web service 就不用多说了。以下说明我们在使用web service经常碰到的问题:

1、web service接口的安全性:web service的接口是直接暴露在web(虽然可以通过一些方式来验证访问者的身份,但实现起来都比较麻烦,或者性能不佳),另如何防止重放攻击也是个问题;
2、web service数据在web上传输是使用明文的方式,数据容易被非法拦截或篡改;
3、web service需要传输较多的数据时的性能需要如何优化。

·  解决

使用 soap extension来解决以上的问题:

1、在soap头加入身份认证信息(称为Passport),Passport身份的一个凭证,在客户端和服务器端都有保存,验证时必须相匹配。passport在soap头是个报文数据,包含执行身份验证需要的信息。passport使用事务标识来防止重放攻击,即有服务端发出事务标识供客户端使用,客户端发出请求时必须包含该事务标识,当服务端响应后,服务端注销原来的事务标识并生成新的事务标识;
2、数据保护,使用数据摘要或对数据进行加密;
3、数据压缩,在数据传输前对数据进行压缩。

·   、概述

本组件在实现上是通过使用Soap扩展(Passport协议)和SecurityExtension协议来实现对Web Service 的扩展。组件提供3个功能:

1、身份认证

     身份认证由Passport协议实现的。登陆、登出以及结束异步事务是通过专门的Passport服务接口(WebService)发送 Passport包实现的。服务请求是通过加入自定义的Soap头(包含有Passport包)来实现的。

     客户端要请求WebService 服务必须先在本地创建执照,并发出登陆请求时,服务端接受到登陆请求,注册客户执照,并把更改后的执照返回给客户段。在以后的服务请求中,根据Passport协议个规定,客户端和服务端不断修改执照信息来完成身份的验证。

     身份认证中在服务器端保存的执照信息采用缓存的方式,当超过一定时间将被注销。

1.1、简单执照验证

     简单执照密码验证包括登陆、请求、登出三个部分。

     登陆在实现上是向服务器专门的Passport访问通道(WebService)发送加密过身份认证的信息(包括用户名、密码、登记号)。服务器解析身份认证信息,并验证用户名和密码(这个验证过程实施者必须重写),当用户名和密码验证通过后,服务端根据登记号在服务器注册其登记号,如果该登记号已经存在,这登陆失败。注册完登记号,服务器将产生一个执照(Guid同登记号),加密后返回给登陆请求者,这时完成登陆。之后客户端发出的请求必须包含此执照,直至登出。

     服务请求过程中,客户端发出的服务请求中包含服务器授予的执照,服务器接收到请求后,首先验证此执照的正确性。通过验证后,执行请求的内容,返回给客户端。

     登出时,服务器将注销授予给客户端的执照,客户端如果还要服务请求必须先登陆。

1.2、事务执照验证

事务执照验证包括登陆、服务请求、登出三个部分。

登陆请求和简单执照验证一样。不同的是服务器注册登记号后,产生一个执照,该执照包含一个事务登记号,事务登记号只能使用一次(同步的状态下)。服务器把执照返回给客户端完成登陆。

服务请求的过程分为2种类型:一种是同步的方式,即客户端发出一个请求后,在接受到服务器响应后再发下一个请求;另一种是异步的方式,即客户端同时向服务器发出多个请求。

同步的方式中,当客户端发出服务请求中包含服务器授予的执照,如果请求中的事务ID尚未被注册,服务器则拒绝服务。事务ID验证通过后,服务器更新事务ID并销毁原事务ID。接着执行请求内容,完成客户端的请求,并发送更新后的执照给客户端。

         异步的方式中,客户端在服务器授予的执照加入异步标识号(称异步ID),发送给服务器,服务端接收到这样的执照后,先执行事务验证。事务验证通过后,验证此事务的异步 ID是否已经被注册,如果已经被注册,则拒绝服务。异步验证通过后,服务端注册异步ID,执行请求内容后把执照在发回给客户端。注意,执照并没有发生改变,同一批异步请求共用一个事务ID。当客户端确认要结束本次的异步请求时(客户端必须确保所有的线程的请求已经结束),发送结束异步请求信息(包括事务ID和结束标志)。服务端将注销该异步请求的所有信息,并生成新的事务ID和更新执照。

         登出时,客户端发送登出请求。服务端将注销所有本次登陆在服务端注册的信息,完成登出。

2、数据保护

通过数据摘要的方式来验证数据的完整性,同时也可以使用数据加密的方式防止重要的数据被非法截获。

3、数据压缩

对webservice的请求和响应的数据进行压缩,默认使用rfc1951描述的进行压缩。实施者可以重写压缩方式。

·  细节

1、Passport

Passport为客户端进行web service 请求和确认服务响应的一种证书。Passport往返于客户端和服务器之间(通过PassportInfo),而且双方在本地都通过管理器保存有Passport的副本。Passport的生成是服务器根据客户端发出登记号产生的,简单执照验证中,Passport一经生成就不在修改,客户端可以重复使用直到登出。而事务执照验证中,Passport中的事务ID将不断改变,这个改变是由服务器发起的,当服务器接受到Passport,验证通过后(登记号和事务ID)将生成新的事务ID并销毁原来的事务ID。对于异步多个请求的方式,服务器将认为是同一个事务,而使用异步ID加以注册。

执照信息(PassportInfo)是保存在Passport服务接口的参数或者命名为Passport的Soap头里,内容是Passport协议报文数据经过加密和Base64编码过的数据。报文内容如下:

Passport协议

报文:

报文标记开头(PS)

D

保留

验证类型

请求类型

PassportID(16字节)

Username(16字节)(可选)

Password(16字节)(可选)

TransactionID(16字节)(可选)

LastTransactionID(16字节)(可选)

AsynchronismID(16字节)(可选)

报文标记开头:16位,固定为PS。

D:1位,报文发送者(0客户端/1服务端)

保留:7位

验证类型:4位

0x0:无验证

0x1:简单执照验证

0x2:事务执照验证

请求类型:4位

请求类型

说明

验证类型

D为0时

D为1时

0x1

登陆请求

0x1

Username、Password必须

 

0x2

TransactionID

0x2

服务请求

0x1

 

 

0x2

TransactionID 必须

TransactionID,LastTransactionID 必须

0x4

异步服务请求

0x2

TransactionID,AsynchronismID必须

TransactionID,AsynchronismID必须

0x5

结束异步服务请求

0x2

TransactionID

TransactionID,LastTransactionID 必须

0xf

登出请求

0x1

 

 

0x2

 

 

PassportInfo先由客户端发出,服务器接收后,进行响应和修改,返回给客户端,客户端对接收到的 PassportInfo 进行验证(PassportID和LastTransactionID,并更新本地的Passport。

2、SoapExtension

Soap扩展从System.Web.Services.Protocols.SoapExtension类派生的,可以在客户端或服务器上处理消息时在特定阶段中检查或修改消息。GetInitializer 和 Initialize 方法提供其他可用机制,用于初始化 SOAP 扩展以增强性能。ProcessMessage 是大多数 SOAP 扩展的核心,原因是该方法在 SoapMessageStage 中定义的每一个阶段都被调用,从而使 SOAP 扩展得以执行所需的该特定 SOAP 扩展的行为。对于需要修改 SOAP 请求或 SOAP 响应的 SOAP 扩展,ChainStream 提供一个机会以接收要通过网络发送的建议数据。(详见SDK文档)

对数据进行操作的顺序:

客户端发出请求:打包加入执照 – 数据摘要/加密– 数据压缩

服务器接受请求:数据解压 – 数据解密/验证摘要 – 执照验证

服务器响应请求:打包加入执照 –数据摘要/加密– 数据压缩

客户端接受响应:数据解压 – 数据解密/验证摘要 – 执照确认/更新

数据摘要默认使用内置的MD5算法。

数据加密默认使用内置的DES算法进行加密,实施者可以重写该方法。

数据压缩默认使用第三方组件ICSharpCode.SharpZipLib 进行压缩,使用 rfc1951中的压缩描述,实施者可以重写该方法。

    其中数据摘要/加密、数据压缩是发生在soap数据序列化之后或反序列化之前,而打包加入执照、执照确认/更新是发生在soap数据反序列化之后或序列化之前。

    数据摘要信息是保存在soap数据流的前面部分。具体格式如下:摘要长度(32位)+摘要+数据。

客户端的发出请求的时候, ServerSecurityExtension先检查本地执照,如果本地没有执照,将创建登陆执照,发出登陆请求,完成登陆后,再发出请求。用户确认要登陆的时候发出登出请求。登陆和登出请求由PassportService WebService类管理。

SecurityExtension 协议定义:

报文:

报文标记开头(SE)

D

保留

压缩类型

压缩参数

保护类型

保护参数

数据摘要+数据

     

报文标记开头:16位,固定为SE。

D:1位,报文发送者(0客户端/1服务端)

保留:15位

压缩类型:4位

已定义的类型:

0x01  组件内置的压缩方案

压缩参数:12位

         与压缩类型对应的压缩的相关参数

0x01方案(4位):

0x0:不压缩;

0x1:最快;

0x2:较快;

0x3:默认;

0x4:较好;

0x5:最好;

保护类型:4位

         已定义的类型:

0x0 未实现保护

0x1 数据摘要

0x2 数据加密

保护参数:12位

         与保护类型对应的保护的相关参数

0x0方案(12位)

0x1方案(12位),前4位为类型,后8位为摘要数据长度:

         0x0:使用内置的MD5算法;                     

0x1:使用.Net框架的HMACSHA1;

0x2:使用.Net框架的MACTripleDES;

0x3:使用.Net框架的MD5CryptoServiceProvider;

0x4:使用.Net框架的SHA1Managed;

0x5:使用.Net框架的SHA256Managed;

0x6:使用.Net框架的SHA384Managed;

0x7:使用.Net框架的SHA512Managed;

0x2 方案(12位),前4位为类型,后8位空

0x0:使用内置的DES算法;

0x1:使用.Net框架的DESCryptoServiceProvider;

0x2:使用.Net框架的RC2CryptoServiceProvider;

0x3:使用.Net框架的RijndaelManaged;

0x4:使用.Net框架的TripleDESCryptoServiceProvider;

·     配置

SecurityExtension 的配置主要是针对一些算法和参数的配置。可以在.config文件定义全局的配置,也可以在SecurityExtensionAttribute定义某个webservice接口的配置。

1、服务端

< configuration >
 
< configSections >
    
< sectionGroup  name ="SecurityExtension" >
        
< section  name ="Configure"  type ="MFW.Component.SecurityExtension.SecurityExtensionConfigureHandler,SecurityExtension"   />
    
</ sectionGroup >
</ configSections >
< appSettings >
    
< add  key ="SecurityExtensionDebugOutputDirectory"  value ="D:\" ></ add >
</ appSettings >
< SecurityExtension >
    
< Configure >
        
< PassportLevel  value ="2" ></ PassportLevel >
        
< Sponsor >
            
< Passport >
                
< Handler  type ="MFW.Component.SecurityExtension.PassportModule.DefaultPassporter,SecurityExtension" ></ Handler >
                
< KeyData  value ="suXh/uz4x7w=" ></ KeyData >
            
</ Passport >
            
< Compress >
                
< Handler  type ="MFW.Component.SecurityExtension.DefaultCompresser,SecurityExtension" ></ Handler >
                
< Level  value ="0" ></ Level >
            
</ Compress >
            
< Protect >
                
< Handler  type ="MFW.Component.SecurityExtension.DefaultProtecter,SecurityExtension" ></ Handler >
                
< Level  value ="0" ></ Level >
                
< KeyData  value ="suXh/uz4x7w=" ></ KeyData >
            
</ Protect >
        
</ Sponsor >
        
< Supporter >
            
< Passport >
                
< Handler  type ="MFW.Component.SecurityExtension.PassportModule.DefaultPassporter,SecurityExtension" ></ Handler >
                
< KeyData  value ="suXh/uz4x7w=" ></ KeyData >
            
</ Passport >
            
< Compress >
                
< Handler  type ="MFW.Component.SecurityExtension.DefaultCompresser,SecurityExtension" ></ Handler >
            
</ Compress >
            
< Protect >
                
< Handler  type ="MFW.Component.SecurityExtension.DefaultProtecter,SecurityExtension" ></ Handler >
                
< KeyData  value ="suXh/uz4x7w=" ></ KeyData >
            
</ Protect >
        
</ Supporter >
    
</ Configure >
</ SecurityExtension >

说明:

SecurityExtensionDebugOutputDirectory 保存服务端接收和响应的数据目录,用于调试用。

Sponsor 发出者的配置,即对应与 Supporter 支持者,一个匹配的对。Sponsor 用于数据的编码,Supporter用于数据的解码。

 

2、客户端

< configuration >
< configSections >
    
< sectionGroup  name ="SecurityExtension" >
        
< section  name ="Configure"  type ="MFW.Component.SecurityExtension.SecurityExtensionConfigureHandler,SecurityExtension"   />
        
< section  name ="PassportAccount"  type ="MFW.Component.SecurityExtension.PassportModule.PassportAccountHandler,SecurityExtension"   />
        
< section  name ="AccessService"  type ="MFW.Component.SecurityExtension.AccessServiceHandler,SecurityExtension"   />
    
</ sectionGroup >
</ configSections >
    
< SecurityExtension >   
        
< Configure >   
            
< PassportLevel  value ="2" ></ PassportLevel >
            
< Sponsor >
                
< Passport >
                    
< Handler  type ="MFW.Component.SecurityExtension.PassportModule.DefaultPassporter,SecurityExtension" ></ Handler >
                    
< KeyData  value ="suXh/uz4x7w=" ></ KeyData >
                
</ Passport >
                
< Compress >
                    
< Handler  type ="MFW.Component.SecurityExtension.DefaultCompresser,SecurityExtension" ></ Handler >
                    
< Level  value ="0" ></ Level >
                
</ Compress >
                
< Protect >
                    
< Handler  type ="MFW.Component.SecurityExtension.DefaultProtecter,SecurityExtension" ></ Handler >
                    
< Level  value ="0" ></ Level >
                    
< KeyData  value ="suXh/uz4x7w=" ></ KeyData >
                
</ Protect >
            
</ Sponsor >
            
< Supporter >
                
< Passport >
                    
< Handler  type ="MFW.Component.SecurityExtension.PassportModule.DefaultPassporter,SecurityExtension" ></ Handler >
                    
< KeyData  value ="suXh/uz4x7w=" ></ KeyData >
                
</ Passport >
                
< Compress >
                    
< Handler  type ="MFW.Component.SecurityExtension.DefaultCompresser,SecurityExtension" ></ Handler >
                
</ Compress >
                
< Protect >
                    
< Handler  type ="MFW.Component.SecurityExtension.DefaultProtecter,SecurityExtension" ></ Handler >
                    
< KeyData  value ="suXh/uz4x7w=" ></ KeyData >
                
</ Protect >
            
</ Supporter >
        
</ Configure >
        
< PassportAccount  username ="admin"  password ="8888" ></ PassportAccount >
        
< AccessService  type ="SecurityExtensionClientTest.PassportAccess.PassportAccess,SecurityExtensionClientTest" ></ AccessService >
    
</ SecurityExtension >
</ configuration >

说明:

PassportAccount 帐户和密码
AccessService Passport服务通道
 

·   使用的注意点

1、   在服务器端加入的webservice 接口加入 [SecurityExtension(Port=PortType.Server)],其中 Port 必须为 PortType.Server。

2、   在服务器端一个webservice页PassportAccess,该类从 PassportAccessService 派生,并实现 ValidateAccount 方法。

3、   在 web.config 加入关于 SecurityExtension 的配置项。

4、   客户端引用 PassportAccess 页,并在代理类加入 IPassportAccess 接口。

5、   在使用 SecurityExtension 的代理类加入 [SecurityExtension(Port=PortType.Client)] ,其中 Port 必须为 PortType.Client。

6、   在app.config 加入关于 SecurityExtension 的配置项。

7、   另组件还处于测试阶段,如果大家发现什么问题或者有什么建议请告诉偶哦。 :)

8、   现在组件只使用内置的算法对数据进行处理,并不支持协议上所定义的。

9、   PS,偶的描述可能不是很清晰哦~~,请大家见量。

 

·    组件代码 V0.1

组件包含两个版本的,一个是framework1.1,另一个是精简版的(只支持client端的,现在有个项目使用WINCE,因此才做了个精简版的)。

下面文件包含组件的源代码、精简版源代码、类库文档和一个简单的demo。
    
     http://files.cnblogs.com/vme/SecurityExtension%20V0.1.rar

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值