WSE3.0构建Web服务安全(4):MTOM消息传输优化和文件上传、下载

本文涉及的产品
密钥管理服务KMS,1000个密钥,100个凭据,1个月
简介:
     MTOM消息优化传输机制主要应用于大量数据的传输,很多文章中也直接得出结论:使用MTOM文件传输效率高。为什么MTOM的数据传输效率会比别的方式要高?MTOM真的如此完美吗,它有什么不足?什么情况下使用MTOM?这些疑问,本文WSE3.0构建Web服务安全系列文章的第4节: MTOM消息优化传输机制和文件上传、下载--将为您一一解答。 本节结构为1.MTOM基础概念2.WSE3.0工具配置MTOM3.代码实现与分析4.总结。最后附上实现代码供大家参考。
    WSE3.0中引入MTOM机制,给我们借助WSE框架实现大量数据的交互带来显著的益处。在WSE 3.0中,我们可以使用MTOM用于服务器端和客户端传递消息,另外的好处就是,WSE 3.0M允我们在传递大数据量时使用WSE 3.0消息层的安全性机制,借助WSE3.0的安全框架,我们不仅可以验证用户的合法性,还可以对消息进行加密,不仅能够保证数据的安全,还可以实现大数据量的高效传输。
   
1.【MTOM基础概念】
   提到MTOM消息优化传输机制,通常的实验结果是使用MTOM传输数据会提高大约33%的性能。 消息传输优化机制 (MTOM) 标准允许将消息中包含的大型数据元素外部化,并将其作为无任何特殊编码的二进制数据随消息一起传送。MTOM 消息会打包为多部分/相关 MIME 序列,放在SOAP 消息中一起传送。
     我们需要了解一些相关的概念。什么是BASE64编码、MTOM消息优化传输机制、MIME。这些对于我们理解MTOM消息优化传输机制问题非常的必要。下面就来做下介绍。
1.1【BASE64编码】
     BASE64编码 的原理很简单,其方法是,将输入数据流每次取6 bit(每bit代表1位二进制),不足6bit的补0,这样,每3个8位字节将编码为4个6位字节(3×8 → 4×6);不满4个字节的以“=”填充。其实这4个六位字节 仍然是8位,只不过高两位被设置为0。当一个字节只有6位有效时,它的取值空间为0 到 2的6次方减1 即63,也就是说被转换的Base64编码的每一个编码的取值空间为(0~63)。
 
  这样就可以将3个8位字节,转换为4个字节,这4个转换的字节都可以映射到字符中。也即数据都可以使用字符编码代替。 因为转换后的字符串要比原来的多一个字节,长1/3。因此编码后的数据长度增加到4/3倍。这里也是为什么使用SOAP消息效率比MTOM低的原因。因为SOAP使用XML语言进行消息传递,XML是基于BASE64编码的语言。
1.2【MIME】
     MIME表示多用途Internet邮件扩允协议。MIME扩允了基本的面向文本的Internet邮件系统,以便可以在消息中包含二进制附件。MIME(Multipurpose Internet Mail Extentions),一般译作"多用途的网络邮件扩充协议"。顾名思义,它可以传送多媒体文件。 MIME (Multipurpose Internet Mail Extensions,多目的Internet邮件扩展)是创建用于电子邮件交换,网络文档,及企业网和Internet上的其他应用程序中的文件格式的规范。
1.3【MTOM消息优化传输】
    MTOM 全称Message Transmission Optimization Mechanism,即消息传输优化机制。它提出的模型适用于大量数据的交互情况。针对Base64编码情况带来的开销提出的解决方案。当数据量小的时候,SOAP依然使用XML进行消息的传递。
     但是在大量数据情况下,如果数据依然进行Base64编码,会带来33%的额外开销,这样的情况对于大量数据交换的情况是无法容忍的。MTOM 就是针对SOAP 消息传输的基础上提出的改进办法。对于大量数据的传递,不会进行进行Base64编码,而是直接以附件的二进制原始数据的形式封装在SOAP消息的MIME 部分,进行传输。SOAP 消息通过指向随其发送的 MIME 部分来引用二进制内容,另外包括SOAP基本的XML 数据,这些还是Base64编码。因为此模型与简单邮件协议SMTP 模型基本一致。
      MTOM通过简化大量数据的编码过程,从而提高数据的处理效率。因为SOAP消息等必要的信息,MTOM 也有一些必要的开销。MTOM仅在二进制数据元素的大小超过大约 1 KB 时,才能体现出其优势。
2.【WSE3.0工具配置MTOM】
     在WSE3.0项目中使用MTOM消息传输优化机制非常的方便,我们可以使用WSE 3.0配置工具分别为Web 服务和Client客户端设置启用MTOM,生成相应的策略文件,WSE3.0机制会根据策略对消息传输使用MTOM(也可以通过代码实现) 。
    数据使用字节流byte[]数组在客户端和服务端进行传输,简单的例子就是消息的交互和文件的上传和下载操作。本次配置基本介绍的情况也是借助WSE3.0的安全机制实现文件的安全传输。
     2.1首先使用WSE 3.0配置工具设置服务端消息传输策略。如图:
客户端设置为on,要求客户端使用MTOM机制进行数据传输。服务端设置为Optional,表示可选,服务端既支持MTOM又可以不支持MTOM编码的消息。适用性强。
此种情况即服务端会根据客户端的请求类型来决定是否启用MTOM机制进行数据传递.如果客户端适用MTOM编码,则服务会启用MTOM处理消息。如果设置为Always,服务端会一直使用MTOM机制进行消息的传递。一般不推荐使用这个方式。OFF即一直不使用MTOM机制进行消息传递。64为最大附加二进制文件的个数。最后表示需要首先使用SOAP消息封装。
  • The optional mode is the default settings. In this mode the WSE processes the incoming SOAP messages whether or not they are MTOM encoded. This gives much more flexibility to web services that are not only dealing with large amount of data. With optional the client is the one who decide whether to use MTOM or not, if the client application request to use MTOM the web service will use MTOM.
  • In always mode all incoming and outgoing SOAP messages must be MTOM encoded. When a SOAP request is received that is not encoded using MTOM, an HTTP error 415: "Media unsupported" is returned to the sender. This option is ideal for Web Services that only deal with large amount of data.
  • In never mode all incoming SOAP messages must not be MTOM encoded. When a SOAP request is received that is encoded using MTOM, an HTTP error 415: "Media unsupported" is returned to the sender. That means the client application should never use MTOM.
     
    对应的配置文件为:
        <messaging>
          <mtom serverMode="optional" clientMode="On" />
        </messaging>
         2.2客户端的设置与服务端类似:
  • 客户端配置文件的代码如下:
        <messaging>
          <mtom clientMode="On" serverMode="optional" />
        </messaging>
    3.【代码实现与分析】
        进行完毕配置以后我们来具体进入代码的开发阶段。这里给出了使用MTOM上传照片的例子,一个使用了证书加密图片上传。先给出服务端的实现,包括两个服务类: WSE3MTOMService和WSE3MTOMSecureService。方法都是二进制字节数据流的传递。
    3.1WSE3MTOMService直接实现基于MTOM机制的图片上传和下载方法,具体实现如下:
    //WSE 3.0 Samples中的MTOM示例演示了:不加密上传、下载文件、
    [WebService(Namespace = "http://www.cnblogs.com/frank_xl/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    public class WSE3MTOMService : System.Web.Services.WebService
    {
        public WSE3MTOMService()
        {
        }
        //此方法返回不加密的字节数组,下载文件
        [WebMethod]
        public byte[] DownLoadFile(string fileName)
        {
            byte[] file = new byte[1024];
            String filePath = AppDomain.CurrentDomain.BaseDirectory + @"App_Data\" + fileName;
            file = File.ReadAllBytes(filePath);
            return file;
        }
        //上传文件,传回2进制数据
        [WebMethod]
        public void UpLoadFile(byte[] file)
        {
            String filePath = AppDomain.CurrentDomain.BaseDirectory + @"App_Data\" + "FrankXuLei.gif";
            if (File.Exists(filePath))
                File.Delete(filePath);
            File.WriteAllBytes(filePath, file);
        }
    }
    3.2WSE3MTOMSecureService定义了一个文件下载的方法。具体如下:
    //WSE 3.0 Samples中的MTOM示例演示了:加密上传、下载文件、
    [WebService(Namespace = "http://www.cnblogs.com/frank_xl/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    //Returns binary data secured via the ServerPolicy in the wse3policyCache.config policy file
    [Policy("ServerPolicy")]
    public class WSE3MTOMSecureService : System.Web.Services.WebService
    {
        public WSE3MTOMSecureService()
        {
        }
        //T通过服务端 X509 证书加密
        // MTOM可以使用WS-Security安全协议.
        [WebMethod]
        public byte[] DownLoadFileWithSecurity(string fileName)
        {
            byte[] file = null;
            String filePath = AppDomain.CurrentDomain.BaseDirectory + @"App_Data\" + fileName;
            file = File.ReadAllBytes(filePath);//从文件里读取字节流
            return file;
        }
    }
    3.3客户端建立控制台应用程序,添加对Web服务的引用。实例化连个代理服务类,进行文件的上传和下载。具体代码如下:
    //直接进行数据传输,不需要加密
            public void DownLoadFile(String fileName)
            {
                //实例化服务代理类
                WSE3MTOMServiceWse serviceproxy = new WSE3MTOMServiceWse();
                //or alternatively set the RequireMtom property on the proxy
                //serviceproxy.RequireMtom = true;
                //获取文件二进制字节流
                byte[] loadFile = serviceproxy.DownLoadFile(fileName);
                //打印数据信息
                Console.WriteLine("File Name: {0}", fileName);
                Console.WriteLine("File has been downloaded without security sucessfully from Server: {0}", loadFile.Length);
                //保存文件
                String filePath = AppDomain.CurrentDomain.BaseDirectory + fileName;
                Console.WriteLine("");
                if (File.Exists(filePath))
                    File.Delete(filePath);
                File.WriteAllBytes(filePath, loadFile);
            }
            //安全方式下载文件
            public void DownLoadFileSecure(String fileName)
            {
                
                WSE3MTOMSecureServiceWse serviceproxy = new WSE3MTOMSecureServiceWse();
                //Set anonymousForCertificateSecurity policy assertion when calling
                //this secure service
                serviceproxy.SetPolicy("ClientPolicy");
                byte[] loadFile = serviceproxy.DownLoadFileWithSecurity(fileName);
                //打印数据信息
                Console.WriteLine("File Name: {0}", fileName);
                Console.WriteLine("File has been downloaded with security sucessfully from Server: {0}", loadFile.Length);
                //保存文件
                String filePath = AppDomain.CurrentDomain.BaseDirectory + "Secure_"+ fileName;
                Console.WriteLine("");
                if (File.Exists(filePath))
                    File.Delete(filePath);
                    File.WriteAllBytes(filePath, loadFile);
            }
            //测试非加密安全上传文件
            public void UpLoadFile(String fileName)
            {
                String filePath = AppDomain.CurrentDomain.BaseDirectory + fileName;
                //实例化服务代理
                WSE3MTOMServiceWse serviceproxy = new WSE3MTOMServiceWse();
                //读取文件数据
                byte[] upFile = File.ReadAllBytes(filePath);
                //调用方法传输数据
                serviceproxy.UpLoadFile(upFile);
                //输出上传文件信息
                Console.WriteLine("File Name: {0}", fileName);
                Console.WriteLine("File has been uploaded sucessfully from Client: {0}", upFile.Length);
            }
    运行结果如图:
        首先是上传一个文件到服务器端,然后进行下载操作。均显示成功。可以在程序的运行目录下找到下载的新文件。
    4.【总结】
        通过以上的介绍和学习,我们知道了一下结论:
    1.MTOM机制会效率提升1/3.原因:正常文本 XML 使用 Base64 对二进制数据进行编码,这要求每三个字节对应四个字符,从而使得数据的大小增加三分之一。MTOM 能够以原始字节形式传输二进制数据,这会缩短编码/解码时间并生成较小的消息。
    2.使用的场合:MTOM适合大量的数据交换,通常是大量数据情况下才有优势, 如上传文档和图片,目的在于优化对较大的二进制负载的传输。
    3.缺陷:对于较小的二进制负载来说,使用 MTOM 发送 SOAP 消息会产生显著的开销。
       另外提供本文的代码下载。以供大家学习参考,代码下载连接 /Files/frank_xl/WSE3MTOM_FrankXuLei.rar。如有意见也欢迎交流~
       Web服务驻留在IIS外,可以由系统服务、控制台程序等托管的方式比较简单,大家可以参考微软的例子,这个WCF里也有类似的寄宿宿主的概念。其实有许多相似之处。
       最后在准备《 WSE3.0构建Web服务安全》系列文章的过程中,我也收获不少,也希望本系列文能给您的学习带来一些帮助。包括我之前的《WCF分布式开发必备知识》系列都是学习WCF分布式重要知识点的总结。并且全部给出了详细的代码实现和注释。方便大家的学习和实际项目的应用。下面我们将正式进入WCF分布式开发的学习阶段,我会继续给出系统的介绍和详细的实现代码。希望有兴趣的朋友继续关注~谢谢
    参考资料:
    1.BASE64编码基于十进制的实现方法
    2.MTOM编码 MSDN



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










    相关文章
    |
    1天前
    |
    XML 安全 PHP
    PHP与SOAP Web服务开发:基础与进阶教程
    本文介绍了PHP与SOAP Web服务的基础和进阶知识,涵盖SOAP的基本概念、PHP中的SoapServer和SoapClient类的使用方法,以及服务端和客户端的开发示例。此外,还探讨了安全性、性能优化等高级主题,帮助开发者掌握更高效的Web服务开发技巧。
    |
    4天前
    |
    前端开发 JavaScript API
    前端框架新探索:Svelte在构建高性能Web应用中的优势
    【10月更文挑战第26天】近年来,前端技术飞速发展,Svelte凭借独特的编译时优化和简洁的API设计,成为构建高性能Web应用的优选。本文介绍Svelte的特点和优势,包括编译而非虚拟DOM、组件化开发、状态管理及响应式更新机制,并通过示例代码展示其使用方法。
    14 2
    |
    4天前
    |
    人工智能 搜索推荐 PHP
    PHP在Web开发中的璀璨星辰:构建动态网站的幕后英雄###
    【10月更文挑战第25天】 本文将带您穿越至PHP的宇宙,揭示其作为Web开发常青树的奥秘。通过生动实例与深入解析,展现PHP如何以简便、高效、灵活的姿态,赋能开发者打造动态交互式网站,同时不忘探讨其在新时代技术浪潮中面临的挑战与机遇,激发对技术创新与应用的无限思考。 ###
    9 1
    |
    5天前
    |
    前端开发 JavaScript 开发者
    构建响应式设计的现代Web应用:实用技巧与工具
    【10月更文挑战第24天】本文介绍了构建响应式Web应用的实用技巧和工具,涵盖流体网格布局、弹性图片、CSS媒体查询、CSS Grid和Flexbox、响应式导航菜单、图片和字体的响应式处理,以及测试和调试工具。掌握这些技能将帮助开发者提升用户体验和项目适应性。
    |
    5天前
    |
    缓存 前端开发 JavaScript
    构建高效、可维护的Web应用
    【10月更文挑战第23天】构建高效、可维护的Web应用
    17 1
    |
    21天前
    |
    XML JSON API
    ServiceStack:不仅仅是一个高性能Web API和微服务框架,更是一站式解决方案——深入解析其多协议支持及简便开发流程,带您体验前所未有的.NET开发效率革命
    【10月更文挑战第9天】ServiceStack 是一个高性能的 Web API 和微服务框架,支持 JSON、XML、CSV 等多种数据格式。它简化了 .NET 应用的开发流程,提供了直观的 RESTful 服务构建方式。ServiceStack 支持高并发请求和复杂业务逻辑,安装简单,通过 NuGet 包管理器即可快速集成。示例代码展示了如何创建一个返回当前日期的简单服务,包括定义请求和响应 DTO、实现服务逻辑、配置路由和宿主。ServiceStack 还支持 WebSocket、SignalR 等实时通信协议,具备自动验证、自动过滤器等丰富功能,适合快速搭建高性能、可扩展的服务端应用。
    81 3
    |
    3天前
    |
    设计模式 前端开发 数据库
    Python Web开发:Django框架下的全栈开发实战
    【10月更文挑战第27天】本文介绍了Django框架在Python Web开发中的应用,涵盖了Django与Flask等框架的比较、项目结构、模型、视图、模板和URL配置等内容,并展示了实际代码示例,帮助读者快速掌握Django全栈开发的核心技术。
    71 44
    |
    4天前
    |
    安全 数据库 开发者
    Python Web开发:Django框架下的全栈开发实战
    【10月更文挑战第26天】本文详细介绍了如何在Django框架下进行全栈开发,包括环境安装与配置、创建项目和应用、定义模型类、运行数据库迁移、创建视图和URL映射、编写模板以及启动开发服务器等步骤,并通过示例代码展示了具体实现过程。
    21 2
    WK
    |
    4天前
    |
    安全 Java 编译器
    C++和Java哪个更适合开发web网站
    在Web开发领域,C++和Java各具优势。C++以其高性能、低级控制和跨平台性著称,适用于需要高吞吐量和低延迟的场景,如实时交易系统和在线游戏服务器。Java则凭借其跨平台性、丰富的生态系统和强大的安全性,广泛应用于企业级Web开发,如企业管理系统和电子商务平台。选择时需根据项目需求和技术储备综合考虑。
    WK
    8 0
    |
    27天前
    |
    设计模式 测试技术 持续交付
    开发复杂Web应用程序
    【10月更文挑战第3天】开发复杂Web应用程序
    31 2