锐捷交换机端口聚合:WSE3.0构建Web服务安全(Web Services Enhancements 增强)

来源:百度文库 编辑:中财网 时间:2024/04/29 00:45:09
继《WCF分布式应用程序开发必备知识》系列之后,经过一周的时间,我准备了关于如何使用WSE3.0进行Web Service安全开发的文章--《WSE3.0构建Web服务安全》,写出来一起与大家分享。《WCF分布式应用程序开发必备知识系列》第4节Web服务已经涉及到Web服务安全的问题。这个系列仍是对以前技术的整理和学习的文章。我在整理的过程中也收获很多,对整个WSE3.0的安全机制有的新的认识。不管高手还是菜鸟,都希望你能从我的这个系列文章里有所收获。那么我们就来一起学习这个系列文章的第一篇:WSE3.0安全机制与实例开发。全部文章分为5个部分:1.WSE3.0框架介绍2.安全基本概念 3.下载与安装4.代码实现与分析5.总结。网上很多参考的文章在介绍WSE安全开发的时候不够系统。往往有文章没代码,或者有代码但运行不了。最后我还会照例放出文章的例子代码。并包括详细的注释。   

     下面我们进入今天的正式学习。

    【1】.WSE3.0框架介绍   

       WSE3.0全称是  Web Services Enhancements 3.0。是微软针对Web Service推出的安全实现平台,包括为了实现安全认证和加密特定的类库。WSE3.0的很多安全实现方式都能在WCF框架里找到影子。WebSerivice 2.0 支持 WS-I Basic Profile 1.1 和 SOAP 1.2。这意味着,它支持 XML 1.0、XML 架构定义 (XSD)、Web 服务描述语言 (WSDL)、SOAP 1.1、SOAP 1.2 以及编译时的基本配置文件一致性验证。WSE 3.0 通过提供对某些更高级的 WS-* 协议的支持,来补充 WebSerivice 2.0 的功能。

        因此我们通常会使用WSE 3.0增强 WebSerivice安全。WSE3.0经常使用的特性包括如下四个方面:

(1)基于消息的安全性 (WS-Security) :支持WS-* 协议

(2)高效的二进制数据传输 (MTOM) :消息传输优化机制Message Transmission Optimization Mechanism

(3)可选的宿主环境 (Host):多个宿主程序的实现,IIS外托管的支持

(4)自定义声明性策略管道(Policy):根据用户需要自定义策略

     首先,WSE 3.0支持WS-* 协议。它是由IBM、Microsoft 和 Verisign 联合发布,是关于 Web 服务安全性(Web Services Security,WS-Security)的规范,该规范提供了一套帮助 Web 服务开发者保护 SOAP 消息交换的机制。这个规范已经被 OASIS 所接受,并且新组建了 Web 服务技术委员会(Web Services Technical Committee,The WSS TC),以促使 WS-Security 成为开放标准。概念性协议栈规定了 Web 服务中构建安全性非常重要的额外元素。路线图中新增的三个部分,策略层中的两个元素和联合层中的一个元素(如图 所示)

   

     各个层次的作用相辅相成。其中WS-Trust 通过定义一组接口开始了定义信任关系的工作,安全性令牌服务将为安全性令牌的发出、交换和验证提供这组接口。它旨在支持创建多种安全性令牌格式,以适应各种认证和授权机制。发出安全性令牌服务接受一个输入请求(通常还有身份证明),然后以指定的身份所请求的令牌(即一个特定的业务证书)作为响应。WS-Secure Conversantion 建立在以安全性令牌为基础的信任这一概念之上。它描述了如何在策略定义的信任关系上下文中使用安全性令牌来使得多个服务请求者和服务提供者能在会话期间安全地交换信息。安全性空间内的这种预期行为的描述也可以称之为信任策略,WS-Policy 框架支持信任伙伴表达和交换他们的信任声明。WS-Trust 定义了整个信任关系的行为,而 WS-SecureConversation 则着重定义了安全通信的安全性上下文(安全性令牌)。

  其次,基于消息的安全性和 消息传输优化机制MTOM 是人们在 Web Serivice项目中使用 WSE3.0 的两个主要原因。另外WSE 3.0 通过Web Serivice提供的扩展来封装对Web Serivice调用。这使我们就能够利用各种 WSE 3.0 功能。在实际开发中我们只需要WSE 3.0设置工具并选择所需的选项。就可以完成对项目的特定设置。这些信息会保存带配置文件里的对应位置。

     再次,多宿主部署。使得我们可以灵活第部署和使用Web Service.而不是单单以来IIS来发布Web服务。WSE 3.0 使您能够执行 Web Serivice类型的自定义宿主。消息处理类 SOAPSender 和 SOAPReceiver 使您能够实现任何类型的高级消息处理模式。WSE 3.0 支持 HTTP 和 TCP协议。允许第三方插入自己的传输实现。

  最后,在 Web Serivice项目中启用 WSE 3.0 的另一个原因是,要利用它的策略管道扩展性模型。WSE 使您能够插入对进入和离开终结点的 SOAP 消息执行预处理和后续处理的筛选器。该扩展点比 WebSerivice SOAPExtension 框架更易于使用,因为它提供的功能可以创建能够与 WSE 提供的现有声明性安全策略相结合的自定义声明性策略。

     另外还可以使用其提供的 SOAP 消息诊断跟踪功能。

    【2】.  安全基本概念

    介绍完WSE3.0的一些基本概念和特性。我们再来熟悉一下常见加密技术、密钥和证书。

    (1)加密技术,为什么要使用加密技术,主要是为了实现一下目的:

    a) 机密性。确保数据的保密性。机密性通常是使用加密实现的。可以使用加密算法(使用加密密钥)将明文转换为密文,并使用相应的解密算法将密文转换回明文。对称加密算法使用相同的密钥进行加密和解密,而非对称算法则使用公钥/私钥对。
    b)数据完整性。确保数据免受意外或者故意(恶意)的修改。完整性通常是由消息身份验证代码或哈希值提供的。哈希值是从数据序列导出的固定长度的数值。哈希值用于验证通过非安全通道传送的数据的完整性。可以将收到的数据的哈希值与传送时数据的哈希值进行比较,以确定数据是否被篡改。
   c)身份验证。保证数据来自某一方。数字证书用于提供身份验证。数字签名通常应用于哈希值,因为这些值比它们所代表的源数据小得多。

   (2)密钥和证书:
    非对称加密使用公钥/私钥对。对于使用私钥加密的数据,只能使用相应的公钥进行解密,反之亦然。(参考MSDN)

   (3)简单介绍一下常见的加密手段如下:

   

表 1: .NET Framework 为其提供现成实现类的算法。

对称算法 非对称算法 哈希算法

DES(数据加密标准)

DSA(数字签名算法)

HMAC SHA1(使用 SHA1 哈希算法且基于哈希的消息身份验证代码)

TripleDES(三重数据加密标准)

RSA

MAC Triple DES(使用 Triple DES 的消息身份验证代码)

Rijndael

 

MD5

RC2

 

SHA1、SHA256、SHA384、SHA512(使用各种哈希大小的安全哈希算法)

    a。私钥加密算法:使用单个私钥来加密和解密数据。由于具有密钥的任意一方都可以使用该密钥解密数据私钥加密又称为对称加密,因为同一密钥既用于加密又用于解密。私钥加密并不能实现数据完整性,即防止数据被更改;也无法完成对身份的验证,即确保数据发自特定的一方。.NET 提供以下实现类以提供对称的密钥加密算法:

DESCryptoServiceProvider

RC2CryptoServiceProvider

RijndaelManaged

TripleDESCryptoServiceProvider


    b.共钥加密:公钥加密使用一个必须对未经授权的用户保密的私钥和一个可以对任何人公开的公钥。公钥和私钥都在数学上相关联;用公钥加密的数据只能用私钥解密,而用私钥签名的数据只能用公钥验证.NET 通过抽象基类 (System.Security.Crytography.AsymmetricAlgorithm) 提供下列非对称(公钥/私钥)加密算法:

DSACryptoServiceProvider

RSACryptoServiceProvider


   c.哈希值:哈希算法将任意长度的二进制值映射为固定长度的较小二进制值,这个小的二进制值称为哈希值。哈希值是一段数据唯一且极其紧凑的数值表示形式。.NET Framework 提供以下实现数字签名算法的类:

NET 提供了下列哈希算法: •

SHA1、SHA256、SHA384、SHA512

MD5

HMACSHA(加密的哈希算法)

MACTripleDES(加密的哈希算法


    d.数字签名:数字签名验证发送方的标识并保护数据的完整性。事实上数字签名是基于以上各种加密技术组合的解决方案。一个基本的数字签名方案可能有如下步骤:双方各自生成一个公钥/私钥对。双方交换他们的公钥。双方生成一个用于对称加密法的私钥,并使用该对称私钥加密要发送的消息。生成加密后消息的哈希值。用对方的共钥加密对称私钥和哈希值(组合密文即为签名),并将该签名附加在消息主体的密文后发送给对方。

   以上知识简单的加密算法的简单介绍,具体大家可以查看相关的安全和加密方面的书籍资料。这里简单介绍是为了更好第理解WSE3.0的安全机制的实现。

    【3】.下载与安装

       下面来介绍一下WSE 3.0的下载和安装情况。

      (1)WSE 3.0下载地址。下载并安装WSE 3.0,你可以选择安装Tools和Samples,开发环境选择Visual Studio 2005插件方式,开发过程中配置Web服务WSE 3.0特性会比较方便。

      安装如图:

     

      一定要选择插件方式,否则我们本地建立项目的时候看不到设置选择下一步直到安装完成。

     (2)Visual Studio 2005 紧密集成 
        可以直接添加web服务引用Add Web Reference/Update Web Reference
        可以进行WSE3.0设置 WSE3.0Settings button 
     (3)单独的工具( Tools) 
       Wse Wsdl生成工具WseWsdl3.exe 
       Wse配置工具WseConfigEditor3.exe 
       X509认证管理工具X509Certificate3.exe

      这些工具都可以在安装目录下找到如图:

   

 

   

 

 

 

 

    WSE 3.0只能和Visual Studio 2005集成安装。Visual Studio 2008里包含了WCF框架类库,WCF 定位为新的 .NET Web 服务平台,该平台能够完全替代现在对 WSE 所提供功能的需要。

    安装完成以后我们新建Web 服务项目。可以在项目右键属性里看到WSE 3.0设置,如图:

      就表示WSE 3.0安装成功并且可以在项目里使用。

     【4】.代码实现与分析

     上面详细讲解了WSE的基本概念、基本加密算法和WSE3.0的安装过程。下面我们来进行具体的代码是实现部分, 之前的《WCF分布式应用程序开发必备知识系列》第4节Web服务已经涉及到Web服务安全的问题。当时的实现机制略有不同,使用的是SOAPHeader传递用户令牌,在服务断进行验证。今天我们使用的是WSE3.类库里实现的类UserNameToken来进行用户名字和密码的传输。项目主要还是包括3个部分。一个Web Service项目、一个UserNameToken类库和测试的客户端

    1)首先来看MyUsernameTokenManager的实现,它继承自UsernameTokenManager,而UsernameTokenManager继承SecurityTokenManagerSecurityTokenManager继承自接口ISecurityTokenManager。UsernameTokenManager其中比较重要的方法是:

        protected virtual string AuthenticateToken(UsernameToken token);

        此方法提供了验证互用令牌的具体实现
        public static WindowsPrincipal LogonUser(string username, string password);

        实现Window策略的验证用户名和密码
        protected virtual void VerifyHashedPassword(UsernameToken token, string authenticatedPassword);
       验证用户的哈希密码

        protected virtual void VerifyPassword(UsernameToken token, string authenticatedPassword);
        验证密码的正确性

        protected virtual void VerifyPlainTextPassword(UsernameToken token, string authenticatedPassword);
       验证这个明文密码的正确性

        public override void VerifyToken(SecurityToken token);

       最后以个是验证用户令牌的包含的用户名和密码的有效性。

       其中最重要的是AuthenticateToken方法。WSE3.0框架会调用我们重写的方法来验证从SoapHeader里提取生成的用户令牌UsernameToken。

      下面我们给处具体的代码:

 

Code
namespace MyUsernameTokenManager
{
    //[SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.AllFlags)]
    public class MyUsernameTokenManager : UsernameTokenManager
    {
        /**//// 
        //构造函数.
        /**//// 

        public MyUsernameTokenManager()
        {
        }

        /**//// 
        /// AuthenticateToken重写实现。任何使用WSE框架安全机制的web服务必须遵守这个契约
        protected override string AuthenticateToken(UsernameToken token)
        {
            // 返回客户端UsernameToken传递的用户密码
            //这里相当于是一个解密的过程。WSE对于客户端的SOAP头信息,
            //反序列化得到的信息生成UsernameToken的实例。

            //这里可以访问数据库获得密码,或者任意密码验证的复杂业务逻辑;
            return "123456789";
        }
    }

}

 

    在代码中重载AuthenticateToken方法。服务端接收到含有UsernameToken实例的SOAP消息后,WSE将 UsernameToken反序列化,并调用VerifyToken方法,而VerifyToken方法在执行过程中又会调用 AuthenticateToken方法,这个方法会返回一个口令值,WSE会拿它与UsernameToken中的口令进行对比。

    2)服务端实现很简单,只包含一个方法,代码如下:

 

Code
using Microsoft.Web.Services3;
//using UsernameTokenManagerFrankXu;
[WebService(Namespace = "http://www.cnblogs.com/frank_xl/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Service : System.Web.Services.WebService
{
    public Service () {

        //Uncomment the following line if using designed components 
        //InitializeComponent(); 
    }

    [WebMethod]
    public string HelloWorld() {
        return "Hello Guys, I 'm Frank Xu Lei";
    }
    
}

 

     3)客户端代码,主要是添加Web 引用。实例化Web服务的代理类,设置UserNameToken来调用web 服务的过程。

     

 

Code
//客户端通过服务代理和服务端交互
namespace WSEUserNametokenClient
{
    class Program
    {
        static void Main(string[] args)
        {
            // 创建Web service proxy的实例 
            ServiceWse serviceProxy = new ServiceWse();
            //通过UsernameToken类的实例添加用户名与口令。
            UsernameToken token = new UsernameToken("FrankXu", "123456789", PasswordOption.SendPlainText);


            // 设置用户令牌到服务代理
            serviceProxy.SetClientCredential(token);

            // 代理设置策略
            //serviceProxy.SetPolicy("ClientPolicy");

            //调用服务方法
            string result = serviceProxy.HelloWorld();
            try
            {
                Console.WriteLine(result);//打印结果
                Console.WriteLine("Calling {0}", result);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

           
            // Success!
            Console.WriteLine("Web Service called successfully");
            //For debug
            Console.WriteLine("Press any key to continue");
            Console.ReadLine();
        }
    }
}

    首先是创建Web service proxy的实例      ServiceWse serviceProxy = new ServiceWse();

    然后通过UsernameToken类的实例添加用户名与口令。使用UsernameToken 设置用户名和密码  UsernameToken token = new UsernameToken("FrankXu", "123456789", PasswordOption.SendPlainText);

    最后 设置用户令牌到服务代理 serviceProxy.SetClientCredential(token)

    调用服务方法  string result = serviceProxy.HelloWorld();

最后运行结果如下:

   

   运行结果显示成功调用了服务,并且输出正确的结果。

   【5】.总结。

     以上是本节的全部内容:WSE3.0框架介绍、安全基本概念、下载与安装、代码实现与分析。这里值得注意的地方:(1)每个项目都要添加WSE3.0程序集Microsoft.Web.Services3的引用,不然项目会报错。最后我还会照例放出文章的(2)例子代码比较简单。只是简单应用了WSE3.0的基本机制。其实不难理解,WSE3.0的用户密码加密就是在客户端设置用户令牌的时候进行。而服务端的AuthenticateToken方法里实现的其具体的密码验证过程,包括具体的验证策略算法等扥,最终返回的就是客户端成精传递的密码。