皮皮网

【亚洲欧洲乱码源码】【博乐达乱码源码】【拍卖系统源码开发】java防重放攻击源码_java防止重放攻击

2024-12-29 18:13:19 来源:fiddler 查看网页源码

1.SSL/TLS协议原理解读
2.网站安全漏洞有哪些
3.Spring Security实现HTTP基本认证详解
4.软件加密与解密的目录
5.如何设计好的RESTful API

java防重放攻击源码_java防止重放攻击

SSL/TLS协议原理解读

        HTTPS是什么相信大家都知道,如果你不知道。。。请关闭此文!!!

        HTTP的数据是明文传输的,没有安全性可言。HTTPS是秘文传输,那么HTTPS是怎么实现数据的安全(加密)传输的?那是因为HTTPS比HTTP多了个'S'。 即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。

        SSL/TLS协议是网络安全通信的重要基石,本文将简单介绍SSL/TLS协议,主要关注SSL/TLS协议的安全性,特别是SSL规范的正确实现。 本系列的文章大体分为几个部分:

        1、SSL/TLS简介

2、SSL/TLS协议的基本流程

3、从SSL到TLS

4、SSL/TLS的流行实现库

        SSL全称是Secure Sockets Layer,安全套接字层,它是由网景公司(Netscape)设计的主要用于Web的安全传输协议,目的是为网络通信提供机密性、认证性及数据完整性保障。如今,SSL已经成为互联网保密通信的工业标准。

        SSL最初的几个版本(SSL 1.0、SSL2.0、SSL 3.0)由网景公司设计和维护,从3.1版本开始,SSL协议由因特网工程任务小组(IETF)正式接管,并更名为TLS(Transport Layer Security),发展至今已有TLS 1.0、TLS1.1、TLS1.2这几个版本。

        如TLS名字所说,SSL/TLS协议仅保障传输层安全。同时,由于协议自身特性(数字证书机制),SSL/TLS不能被用于保护多跳(multi-hop)端到端通信,而只能保护点到点通信。

        SSL/TLS协议能够提供的安全目标主要包括如下几个:

        认证性——借助数字证书认证服务器端和客户端身份,防止身份伪造

        机密性——借助加密防止第三方窃听

        完整性——借助消息认证码(MAC)保障数据完整性,防止消息篡改

        重放保护——通过使用隐式序列号防止重放攻击

        为了实现这些安全目标,SSL/TLS协议被设计为一个两阶段协议,分为握手阶段和应用阶段:

        握手阶段也称协商阶段,在这一阶段,客户端和服务器端会认证对方身份(依赖于PKI体系,利用数字证书进行身份认证),并协商通信中使用的安全参数、密码套件以及MasterSecret。后续通信使用的所有密钥都是通过MasterSecret生成。

        在握手阶段完成后,进入应用阶段。在应用阶段通信双方使用握手阶段协商好的密钥进行安全通信。

        Handshake协议:包括协商安全参数和密码套件、服务器身份认证(客户端身份认证可选)、密钥交换;

        ChangeCipherSpec 协议:一条消息表明握手协议已经完成;

        Alert 协议:对握手协议中一些异常的错误提醒,分为fatal和warning两个级别,fatal类型的错误会直接中断SSL链接,而warning级别的错误SSL链接仍可继续,只是会给出错误警告;

        Record 协议:包括对消息的分段、压缩、消息认证和完整性保护、加密等。

        图2、图3都是表示的协议流程,大同小异。可以对比着看加深理解。

        每一个SSL/TLS链接都是从握手开始的,握手过程包含一个消息序列,用以协商安全参数、密码套件,进行身份认证以及密钥交换。握手过程中的消息必须严格按照预先定义的顺序发生,否则就会带来潜在的安全威胁。今年顶级安全会议CCS 有文章提出了建立综合状态机来检查SSL链接中消息序列……

        2.1 握手过程中的消息序列

        ClientHello:ClientHello通常是握手过程中的第一条消息,用于告知服务器客户端所支持的密码套件种类、最高SSL/TLS协议版本以及压缩算法。

        ClientHello中还包含一个随机数,这个随机数由4个字节的当前GMT UNIX时间以及个随机选择的字节组成,共字节。该随机数会在密钥生成过程中被使用。

        另外,ClientHello中还可能包含客户端支持的TLS扩展。(TLS扩展可以被用来丰富TLS协议的功能或者增强协议的安全性)

        ServerHello:服务器接受到ClientHello后,会返回ServerHello。服务器从客户端在ClientHello中提供的密码套件、SSL/TLS版本、压缩算法列表里选择它所支持的项,并把它的选择包含在ServerHello中告知客户端。接下来SSL协议的建立就基于服务器选择的密码套件类型、SSL/TLS协议版本以及压缩算法。

        ServerHello中同样会包含一个随机数,同样4+ 字节类型,由服务器生成。

        Certificate:客户端和服务器都可以发送证书消息来证明自己的身份,但是通常客户端证书不被使用。 服务器一般在ServerHello后会接一条Certificate消息,Certificate消息中会包含一条证书链,从服务器证书开始,到Certificate authority(CA)或者最新的自签名证书结束。下图形象地描述了证书链:

        SSL中使用的证书通常是X.类型证书,X.证书的内容如下表所示:

        在用的X.证书包含Version 1和Version 3两种版本,其中v1版本的证书存在安全隐患,同时不支持TLS扩展,被逐渐弃用。现在大多数在用的SSL证书都是V3版本。

        同时证书会附带与协商好的密钥交换算法对应的密钥。密钥交换算法以及它们所要求的密钥类型如下表所示。

        ServerKeyExchange:该消息仅当以下密钥交换算法被使用时由服务器发出:

        RSA_EXPORT(仅当服务器的公钥大于bit时)、DHE_DSS、DHE_DSS_EXPORT、DHE_RSA、DHE_RSA_EXPORT、DH_anon 使用其它密钥交换算法时,服务器不能发送此消息。

        ServerkeyExchange消息会携带这些密钥交换算法所需要的额外参数,以在后续步骤中协商PreMasterSecret。这些参数需要被签过名。

        CertificateRequest:这个消息通常在要求认证客户端身份时才会有。消息中包含了证书类型以及可接受的CA列表。

        ServerHelloDone:服务器发送这条消息表明服务器部分的密钥交换信息已经发送完了,等待客户端的消息以继续接下来的步骤。这条消息只用作提醒,不包含数据域。

        ClientKeyExchange:这条消息包含的数据与所选用的密钥交换算法有关。

        如果选择的密钥交换算法是RSA,那么消息包含的参数为用服务器RSA公钥(包含在之前证书中的或者是ServerKeyExchange中的)加密过的PreMasterSecret,它有个字节,前2个字节表示客户端支持的最高协议版本,后个字节是随机选择的。

        如果选择的密钥交换算法是DH或者DHE,则可能有两种情况:

        隐式DH公开值:包含在Certificate消息里;

        显示DH公开值:公开值是本消息的一部分。

        CertificateVerify:这条消息用来证明客户端拥有之前提交的客户端证书的私钥。

        Finished:表明握手阶段结束。这是第一条用协商的算法和密钥保护的消息。

        因为是用协商好的密钥加密的消息,它可以用来确认已经协商好的密钥。

        同时Finished消息包含一个verify_data域,可以用来校验之前发送和接收的信息。

        Verify_data域是一个PRF函数的输出(pseudo-random function)。这个伪随机函数的输入为:(1)两个hash值:一个SHA-1,一个MD5,对之前握手过程中交换的所有消息做哈希;(2)the MasterSecret,由预备主密钥生成;(3)finished_label,如果客户端发送的则是”client finished”,服务器发送的则是”server finished”。关于这个PRF的细节在3.3节中会具体描述。 此外,Finished 消息不能够在ChangeCipherSpec前发送。

        2.2 不同密钥交换算法对应的握手过程

        不同的密钥交换算法对应的握手过程中的消息序列是不同的,相应的实现方式也不同,本节介绍几个常见密钥交换算法对应的握手过程。

        TLS-RSA:在这个场景下,PreMasterSecret是由客户端指定的,并用RSA公钥加密发送给服务器。服务器不影响PReMasterSecret的生成。

        TLS-DH:基于DH的密钥交换也被称为静态Diffie-Hellman。在这种场景下,可能是双方各自提交一个证书包含DH公开值,或者服务器端提交证书包含DH公开值,客户端在每次会话中选择一个值。协商好的DH值被用作PreMasterSecret。显然证书中的参数是固定的,那么每次链接的PreMasterSecret也是相同的。

        TLS-DH不能提供前向安全性。

        TLS-DHE:基于DHE的TLS握手中会有ServerKeyExchange消息。握手过程中交换参数的认证通过数字签名来实现,支持的签名算法包括RSA和DSS。DH参数会有它的数字签名一起被包含在ServerKeyExchange中被发送出去。客户端在ClientKeyExchange中返回它的公开DH参数,但没有签名保护。同样协商出来的DH密钥被用作PreMasterSecret。

        2.3 密钥生成

        Pseudo-random Function(PRF):伪随机函数是SSL协议中的一个重要组成部分,它被用来秘密扩展以及生成密钥。在3.1节讲解Finished消息时已经简单提及PRF,在这里我们详细讨论PRF的工作原理。SSL/TLS协议中的PRF如下图所示:

        这个PRF基于两个hash函数:MD5和SHA-1,它有3个输入,一个Secret(比如PreMasterSecret),一个标志符(比如”client finished”,防重放攻a防放攻 “server finished”),还有一个种子值(比如客户端随机数+服务器端随机数)。

        Secret在使用时被分为长度相同的两半:S1和S2,分别作为P_MD5和P_SHA-1的输入。

        PRF的输出按如下方式处理得到:

        P_MD5和P_SHA-1都是扩展函数,用来扩展秘密值以用于密钥生成,它们的计算方式如下:

        其中A(0) = seed, A(i) = HMAC hash( secret, A( i −1) )

        这个秘密扩展会一直进行直到得到足够多的扩展数据。 Key Derivation:主密钥(MasterSecret)是利用上述PRF从预备主密钥(PreMasterSecret)生成的。每个MasterSecret为字节,生成方式如下:

        得到MasterSecret后,它会被进一步处理最后生成4个不同的密钥和2个初始向量(IV)。处理过程如下:

        处理过程一直持续到足够多的输出被生成,然后把输出分为4个key和2个IV:

        下图完整阐述了SSL/TLS协议中的密钥生成过程。

        本节介绍SSL/TLS协议的版本变迁,不同版本的区别以及安全特性等。

        SSL 1.0由于从来没有被公开过,并且存在严重安全漏洞,我们就不讨论了。

        SSL 2.0:SSL 2.0于年4月被发布。SSL 2.0中主要存在的问题如下:

        MAC不能覆盖填充长度域,攻击者可能利用这点破坏消息完整性;

        缺乏握手认证,攻击者可以篡改密码套件列表,诱骗通信双方使用较弱的密码套件;

        使用较弱的或有问题的密码算法(如MD5,RC4等),或者使用不安全的分组模式(如CBC模式);

        对于不同的密码学基元使用相同的密钥,违背基本安全常识。

        由于以上安全问题,RFC 已经明确提出避免使用SSL 2.0,但是现实生活中还有少量客户端和服务器支持SSL 2.0.

        SSL 3.0:SSL 3.0引入了一些新的特性和机制解决了很多之前版本存在的漏洞。此外,SSL 3.0中引入了ChangeCipherSpec子协议。SSL 3.0向后兼容SSL 2.0,相对于SSL 2.0,它的主要改变包括以下几点:

        支持更多的密码套件(支持更多的密码算法如DSS,SHA-1)

        在握手阶段支持密钥协商(DH和FORTEZZA)

        支持密码学参数的重协商

        增加了消息压缩选项

        MAC能够覆盖填充长度域了,同时MAC可以使用MD5或者SHA-1

        不同的密码学基元使用不同的key

        Alert子协议能对任何错误给出两种提示:Warning和Fatal

        中止链接的时候会用一个close_notify警告通知通信双方

        支持证书链,而非单个证书

        通过Finished消息认证所有发送和接收的消息

        加密了的PreMasterSecret包含当前使用的协议版本,防止协议回滚

        TLS 1.0:TLS 1.0和SSL 3.0差别非常小。实际上,TLS 1.0是SSL 3.1,在IETF接手后改名为TLS。TLS 1.0版本是目前使用最广泛的SSL/TLS协议版本。

        TLS 1.0不再支持使用FORTEZZA的密码套件。

        TLS 1.0中MAC被替换成HMAC。

        之前提到ChangeCipherSpec消息必须在Finished消息前发送,在TLS 1.0中,如果消息序列不符合这个要求,会产生FATAL警告并终止链接。

        TLS 1.1:这个版本相比之前改动也很小。最重要的改动是预防了针对CBC分组模式的一些攻击。现在的填充错误变的和非法MAC错误不可区分了,防止攻击者利用可区分错误响应建立解密预言机对密文进行攻击。

        在每次加密过程中,使用CBC分组模式时,都需要显示给出IV,而不用再密钥生成时使用PRF生成IV。

        此外,TLS 1.1禁止为适应之前出口限制而使用弱化的密码套件。

        TLS 1.2:这是最新的版本,部署的还比较少。这个版本禁用了PRF中的MD5和SHA-1,而用一个可配置的hash函数取代了它们,这样的修改简化了计算过程。修改后的PRF风格如下:

        此外,TLS 1.2的一个重要变化是支持认证加密模式(支持GCM等)。但是由于一些AEAD(Authenticated Encryption with Associated Data)密码算法要求IV为隐式的,所以IV又恢复到由MasterSecret生成,即TLS 1.0以前的风格。

        TLS 1.2支持使用GCM、CCM的新密码套件。

        同时SSL 2.0被宣布放弃,不再向后兼容SSL 2.0.

        本节简单介绍一下流行的SSL/TLS实现库,SSL协议非常复杂,由开发者自己实现常常会出错,开发者在具体实现SSL协议时通常会依赖于这些密码学库。

        4.1 常见的SSL/TLS 实现

        OpenSSL:这是非常流行的开源SSL/TLS实现。

        OpenSSLim完全用C语言实现,支持SSL 2.0/3.0,TLS 1.0/1.1/1.2以及DTLS 1.0。

        OpenSSL 近年来出现了很多的安全漏洞,比如年曝出的著名的Heartbleed漏洞等。

        JSSE:这是使用Java实现的,支持SSL 3.0,TLS 1.0/1.1/1.2.

        Bouncy Castle:它不仅仅支持SSL/TLS,它是一个完整的密码学库,支持各种密码学算法和协议。不过它仅仅支持TLS 1.0版本。

        Android平台主要使用这个密码学库。

        GnuTLS:这是另一个用C语言实现的库,支持SSL 3.0,TLS 1.0/1.1/1.2以及DTLS 1.0。主要在Unix世界被使用。同时以各种安全漏洞多而闻名。

        NSS:这是最初由网景公司(Netscape)开发的库,支持SSL 2.0/3.0,TLS 1.0/1.1,现在主要被浏览器和客户端软件使用,比如Firefox使用的就是NSS库,Chrome使用的是一个NSS库的修正版。

        下表是一些常见软件以及它们所使用的SSL/TLS实现库的情况:

        其它还有一些常用的SSL实现库,如cryptlib、CyaSSL、MatrixSSL、PolarSSL等,由于市场占有率不高,我们这里就不多做介绍了。

        4.2 流行SSL/TLS实现库的安全研究

        最近几年曝出的高风险SSL安全漏洞大多跟SSL实现库有关,比如年4月曝出的“心脏滴血”漏洞,存在于OpenSSL 1.0.1-1.0.1f版本中,影响全球近%的Web服务器;同样是年曝出的苹果公司iOS 7.0.6版本系统中存在的“gotofail”漏洞,因为程序员的疏忽导致SSL证书校验中的签名校验失效;包括今年曝出的SSL Freak攻击也是由于SSL实现库的安全漏洞导致的攻击,我们研究小组的同学对这个攻击有详细的分析,参见《SSL Freak来袭:如何实施一个具体的SSL Freak攻击》。同时我们还开发了一个基于python的中间人代理攻击框架“风声”对某国内知名电商的服务器进行具体的攻击,并上报了漏洞。

        考虑到大量SSL/TLS实现库中存在安全问题,同时这些主流的SSL/TLS实现库对开发者而言使用难度较高,比如有些SSL/TLS实现库要求开发者自己进行随机数生成或密钥管理,让缺乏系统信息安全知识培训的开发者去使用这样高度复杂的密码学库容易产生很多安全问题。我们在这里推荐一些高级密码学库:Google keycazer、NaCl、Cryptlib、GPGME。这些密码学库存在的安全问题较少,同时封装了一些底层的密码学操作,降低了开发者的使用难度。

        以上就是本次要介绍的SSL /TLS协议基本知识,后续的文章我们会对一些典型SSL/TLS攻击进行具体介绍。

        参考:

        1、 blogs.com/NathanYang/p/.html

        3、 blogs.com/bhlsheji/p/.html

网站安全漏洞有哪些

       网站的安全漏洞是普遍存在的,但是击源击也需要适当补救才行,否则的止重话就会酿成恶果。那网站安全漏洞有哪些呢了解网络安全常识,防重放攻a防放攻首先就要了解计算机网络安全有哪些基本注意事项,击源击下面小编就带您认识一下吧。止重亚洲欧洲乱码源码

       1、防重放攻a防放攻越权

       问题描述:不同权限账户之间存在越权访问。击源击

       修改建议:加强用户权限的止重验证。

       注意:

       往往通过不同权限用户之间链接访问、防重放攻a防放攻cookie、击源击修改id等

       2、止重明文传输

       问题描述:对系统用户口令保护不足,防重放攻a防放攻攻击者可以利用攻击工具,击源击从网络上窃取合法的止重用户口令数据。

       修改建议:传输的密码必须加密。

       注意:所有密码要加密。要复杂加密。不要用base或md5。

       3、sql注入

       问题描述:攻击者利用sql注入漏洞,博乐达乱码源码可以获取数据库中的多种信息,如:管理后台的密码,从而脱取数据库中的内容(脱库)。

       修改建议:对输入参数进行过滤、校验。采用黑白名单方式。

       注意:过滤、校验要覆盖系统内所有的参数。

       4、跨站脚本攻击

       问题描述:对输入信息没有进行校验,攻击者可以通过巧妙的方法注入恶意指令代码到网页。这种代码通常是JavaScript,但实际上,也可以包括Java、VBScript、ActiveX、Flash或者普通的HTML。攻击成功之后,攻击者可以拿到更高的权限。

       修改建议:对用户输入进行过滤、拍卖系统源码开发校验。输出进行HTML实体编码。

       注意:过滤、校验、HTML实体编码。要覆盖所有参数。

       5、文件上传漏洞

       问题描述:没有对文件上传限制,可能会被上传可执行文件,或脚本文件。进一步导致服务器沦陷。

       修改建议:严格验证上传文件,防止上传asp、aspx、asa、php、jsp等危险脚本。同事最好加入文件头验证,防止用户上传非法文件。

       6、贷款app源码论坛后台地址泄露

       问题描述:后台地址过于简单,为攻击者攻击后台提供了便利。

       修改建议:修改后台地址链接,复杂点。

       7、敏感信息泄露

       问题描述:系统暴露内部信息,如:网站的绝对路径、网页源代码、SQL语句、中间件版本、程序异常等信息。

       修改建议:对用户输入的异常字符过滤。屏蔽一些错误回显,如自定义、、等。

       8、命令执行漏洞

       问题描述:脚本程序调用如php的system、exec、shell_exec等。gotv资源源码

       修改建议:打补丁,对系统内需要执行的命令要严格限制。

       9、目录遍历漏洞

       问题描述:暴露目录信息,如开发语言、站点结构

       修改建议:修改相关配置。

       、会话重放攻击

       问题描述:重复提交数据包。

       修改建议:添加token验证。时间戳或这验证码。

       、CSRF(跨站请求伪造)

       问题描述:使用已经登陆用户,在不知情的情况下执行某种动作的攻击。

       修改建议:添加token验证。时间戳或这验证码。

       、任意文件包含、任意文件下载

       问题描述:任意文件包含,系统对传入的文件名没有合理的校验,从而操作了预想之外的文件。任意文件下载,系统提供了下载功能,却未对下载文件名进行限制。

       修改建议:对用户提交的文件名限制。防止恶意的文件读取、下载。

       、设计缺陷/逻辑错误

       问题描述:程序通过逻辑实现丰富的功能。很多情况,逻辑功能存在缺陷。比如,程序员的安全意识、考虑的不周全等。

       修改建议:加强程序的设计和逻辑判断。

       关于网络安全小知识,佰

       佰安全网小编为您介绍和普及这么多了,看完上面的介绍,您对“网站安全漏洞有哪些”这个问题了解多少了呢综上我们可以看到,网络安全漏洞也是形形色色个不一样的,所以了解的漏洞的存在对于我们日后的安全生活很重要

Spring Security实现HTTP基本认证详解

       前言

       在上一章节中,我们搭建了第一个Spring Security项目,学习了如何利用Spring Security保护Java Web项目。然而,对于SpringSecurity的细节,还有很多需要深入了解。本文将从认证方式开始,与大家共同学习各种认证。

       一. Spring Security的认证方式

       认证概念:认证是判断系统中是否存在某用户,并判断其身份合法性,解决用户登录问题。其目的是保护系统隐私数据与资源,确保仅合法用户能访问资源。

       认证方式:Spring Security中常见方式包括HTTP层面认证与表单认证,具体有HTTP基本认证、Form表单认证、HTTP摘要认证。

       二. HTTP基本认证

       基本认证概述:在三种方式中,基本认证是最简单的一种。Spring Security 4.x默认采用基本认证,通过弹窗要求用户输入用户名和密码。每次请求时,Authorization头使用Base编码“用户名:密码”。尽管安全性较低,但它是现代认证的基础,Spring Security OAuth的默认认证方式也是如此。

       基本认证核心API:执行流程包括过滤器、构建令牌、AuthenticationManager处理、转给Provider处理等步骤。具体实现步骤如代码所示,执行流程简单。

       基本认证步骤:分为四步,包括发起请求、服务器返回响应并说明认证形式、客户端弹出对话框输入用户名密码、服务器解码验证信息。

       基本认证弊端:无状态认证,无法携带Session信息,不支持Remember-Me功能。用户名密码以明文形式传输,极易被窃听和重放攻击。

       三. 代码实现

       通过理论知识,让我们动手实现基本认证。创建SecurityConfig配置类,继承WebSecurityConfigurerAdapter,开启基本认证。链式编程风格符合设计模式。

       代码结构:核心代码简短,项目包结构随个人创建,实现步骤包括创建配置类、启动项目。

       四. Basic认证详解

       实现基本认证后,本文将深入分析认证过程。Basic Authorization响应头包含WWW-Authenticate信息,分别表示认证类型、认证域。realm概念允许不同域请求时使用不同用户名/密码认证。

       基本认证过程:响应码为,浏览器弹出对话框要求输入用户名/密码,信息进行Base编码后发送给后台认证。认证错误时,浏览器保持弹框;认证成功后,信息缓存在浏览器中,后续请求自动携带。

       注销Basic认证:认证信息缓存在浏览器中,直到关闭浏览器才会销毁。前端可通过手动配置错误的Authorization或使用特定方法清除认证信息,但某些浏览器无效。

       总结:通过几行代码实现基本认证,并了解了注销认证的方法。对于本文内容,欢迎分享你的见解或提问。我将提供Java学习资源,包括教程、源码等,助力你的学习进步。

软件加密与解密的目录

       ã€Šè½¯ä»¶åŠ å¯†ä¸Žè§£å¯†ã€‹

       ç¬¬1ç«  什么是隐蔽软件 1

       1.1 概述 1

       1.2 攻击和防御 5

       1.3 程序分析的方法 6

       1.4 代码混淆

       1.4.1 代码混淆的应用

       1.4.2 混淆技术概述

       1.4.3 被黑客们使用的代码混淆技术

       1.5 防篡改技术

       1.5.1 防篡改技术的应用

       1.5.2 防篡改技术的例子

       1.6 软件水印

       1.6.1 软件水印的例子

       1.6.2 攻击水印系统

       1.7 软件相似性比对

       1.7.1 代码剽窃

       1.7.2 软件作者鉴别

       1.7.3 软件“胎记”

       1.7.4 软件“胎记”的案例

       .1.8 基于硬件的保护技术

       1.8.1 把硬件加密锁和软件一起发售

       1.8.2 把程序和cpu绑定在一起

       1.8.3 确保软件在安全的环境中执行

       1.8.4 加密可执行文件

       1.8.5 增添物理防护

       1.9 小结

       1.9.1 使用软件保护技术的理由

       1.9.2 不使用软件保护技术的理由

       1.9.3 那我该怎么办呢

       1. 一些说明

       ç¬¬2ç«  攻击与防御的方法

       2.1 攻击的策略

       2.1.1 被破解对象的原型

       2.1.2 破解者的动机

       2.1.3 破解是如何进行的

       2.1.4 破解者会用到的破解方法

       2.1.5 破解者都使用哪些工具

       2.1.6 破解者都会使用哪些技术

       2.1.7 小结

       2.2 防御方法

       2.2.1 一点说明

       2.2.2 遮掩

       2.2.3 复制

       2.2.4 分散与合并

       2.2.5 重新排序

       2.2.6 映射

       2.2.7 指引

       2.2.8 模仿

       2.2.9 示形

       2.2. 条件—触发

       2.2. 运动

       2.2. 小结

       2.3 结论

       2.3.1 对攻击/防御模型有什么要求

       2.3.2 该如何使用上述模型设计算法

       ç¬¬3ç«  分析程序的方法

       3.1 静态分析

       3.1.1 控制流分析

       3.1.2 数据流分析

       3.1.3 数据依赖分析

       3.1.4 别名分析

       3.1.5 切片

       3.1.6 抽象解析

       3.2 动态分析

       3.2.1 调试

       3.2.2 剖分

       3.2.3 trace

       3.2.4 模拟器

       3.3 重构源码

       3.3.1 反汇编

       3.3.2 反编译

       3.4 实用性分析

       3.4.1 编程风格度量

       3.4.2 软件复杂性度量

       3.4.3 软件可视化

       3.5 小结

       ç¬¬4ç«  代码混淆

       4.1 保留语义的混淆转换

       4.1.1 算法obfcf:多样化转换

       4.1.2 算法obftp:标识符重命名

       4.1.3 混淆的管理层

       4.2 定义

       4.2.1 可以实用的混淆转换

       4.2.2 混淆引发的开销

       4.2.3 隐蔽性

       4.2.4 其他定义

       4.3 复杂化控制流

       4.3.1 不透明表达式

       4.3.2 算法obfwhkd:压扁控制流

       4.3.3 使用别名

       4.3.4 算法obfctjbogus:插入多余的控制流

       4.3.5 算法obfldk:通过跳转函数执行无条件转移指令

       4.3.6 攻击

       4.4 不透明谓词

       4.4.1 算法obfctjpointer:从指针别名中产生不透明谓词

       4.4.2 算法obfwhkdopaque:数组别名分析中的不透明值

       4.4.3 算法obfctjthread:从并发中产生的不透明谓词

       4.4.4 攻击不透明谓词

       4.5 数据编码

       4.5.1 编码整型数

       4.5.2 混淆布尔型变量

       4.5.3 混淆常量数据

       4.5.4 混淆数组

       4.6 结构混淆

       4.6.1 算法obfwcsig:合并函数签名

       4.6.2 算法obfctjclass:分解和合并类

       4.6.3 算法obfdmrvsl:摧毁高级结构

       4.6.4 算法obfajv:修改指令编码方式

       4.7 小结

       ç¬¬5ç«  混淆理论

       5.1 定义

       5.2 可被证明是安全的混淆:我们能做到吗

       5.2.1 图灵停机问题

       5.2.2 算法reaa:对程序进行反混淆

       5.3 可被证明是安全的混淆:有时我们能做到

       5.3.1 算法obflbs:混淆点函数

       5.3.2 算法obfns:对数据库进行混淆

       5.3.3 算法obfpp:同态加密

       5.3.4 算法obfcejo:白盒des加密

       5.4 可被证明是安全的混淆:(有时是)不可能完成的任务

       5.4.1 通用混淆器

       5.4.2 混淆最简单的程序

       5.4.3 对混淆所有程序的不可能性的证明

       5.4.4 小结

       5.5 可被证明为安全的混淆:这玩儿还能成吗

       5.5.1 跳出不可能性的阴霾

       5.5.2 重新审视定义:构造交互式的混淆方法

       5.5.3 重新审视定义:如果混淆不保留语义又当如何

       5.6 小结

       ç¬¬6ç«  动态混淆

       6.1 定义

       6.2 代码迁徙

       6.2.1 算法obfkmnm:替换指令

       6.2.2 算法obfagswap:自修改状态机

       6.2.3 算法obfmamdsb:动态代码合并

       6.3 加密技术

       6.3.1 算法obfcksp:把代码作为产生密钥的源泉

       6.3.2 算法obfagcrypt:结合自修改代码和加密

       6.4 小结

       ç¬¬7ç«  软件防篡改

       7.1 定义

       7.1.1 对篡改的监测

       7.1.2 对篡改的响应

       7.1.3 系统设计

       7.2 自监测

       7.2.1 算法tpca:防护代码之网

       7.2.2 生成hash函数

       7.2.3 算法tphmst:隐藏hash值

       7.2.4 skype中使用的软件保护技术

       7.2.5 算法rewos:攻击自hash算法

       7.2.6 讲评

       7.3 算法retcj:响应机制

       7.4 状态自检

       7.4.1 算法tpcvcpsj:易遭忽视的hash函数

       7.4.2 算法tpjjv:重叠的指令

       7.5 远程防篡改

       7.5.1 分布式监测和响应机制

       7.5.2 解决方案

       7.5.3 算法tpzg:拆分函数

       7.5.4 算法tpslspdk:通过确保远程机器硬件配置来防篡改

       7.5.5 算法tpcns:对代码进行持续的改变

       7.6 小结

       ç¬¬8ç«  软件水印

       8.1 历史和应用

       8.1.1 应用

       8.1.2 在音频中嵌入水印

       8.1.3 在图片中嵌入水印

       8.1.4 在自然语言文本中嵌入水印

       8.2 软件水印

       8.3 定义

       8.3.1 水印的可靠性

       8.3.2 攻击

       8.3.3 水印与指纹

       8.4 使用重新排序的方法嵌入水印

       8.4.1 算法wmdm:重新排列基本块

       8.4.2 重新分配资源

       8.4.3 算法wmqp:提高可靠性

       8.5 防篡改水印

       8.6 提高水印的抗干扰能力

       8.7 提高隐蔽性

       8.7.1 算法wmmimit:替换指令

       8.7.2 算法wmvvs:在控制流图中嵌入水印

       8.7.3 算法wmcc:抽象解析

       8.8 用于隐写术的水印

       8.9 把水印值分成几个片段

       8.9.1 把大水印分解成几个小片段

       8.9.2 相互冗余的水印片段

       8.9.3 使用稀疏编码提高水印的可靠性

       8. 图的编/解码器

       8..1 父指针导向树

       8..2 底数图

       8..3 排序图

       8..4 根延伸的平面三叉树枚举编码

       8..5 可归约排序图

       8. 讲评

       8..1 嵌入技术

       8..2 攻击模型

       ç¬¬9ç«  动态水印

       9.1 算法wmct:利用别名

       9.1.1 一个简单的例子

       9.1.2 水印识别中的问题

       9.1.3 增加数据嵌入率

       9.1.4 增加抵御攻击的抗干扰性能

       9.1.5 增加隐蔽性

       9.1.6 讲评

       9.2 算法wmnt:利用并发

       9.2.1 嵌入水印的基础构件

       9.2.2 嵌入示例

       9.2.3 识别

       9.2.4 避免模式匹配攻击

       9.2.5 对构件进行防篡改处理

       9.2.6 讲评

       9.3 算法wmccdkhlspaths:扩展执行路径

       9.3.1 水印的表示和嵌入

       9.3.2 识别

       9.3.3 讲评

       9.4 算法wmccdkhlsbf:防篡改的执行路径

       9.4.1 嵌入

       9.4.2 识别

       9.4.3 对跳转函数进行防篡改加固

       9.4.4 讲评

       9.5 小结

       ç¬¬ç«  软件相似性分析

       .1 应用

       .1.1 重复代码筛选

       .1.2 软件作者鉴别

       .1.3 剽窃检测

       .1.4 胎记检测

       .2 定义

       .3 基于k-gram的分析

       .3.1 算法ssswawinnow:有选择地记录k-gram hash

       .3.2 算法ssswamoss:软件剽窃检测

       .3.3 算法ssmckgram:java 字节码的k-gram“胎记”

       .4 基于api的分析

       .4.1 算法sstnmm:面向对象的“胎记”

       .4.2 算法sstonmm:动态函数调用“胎记”

       .4.3 算法sssdl:动态k-gram api“胎记”

       .5 基于树的分析

       .6 基于图的分析

       .6.1 算法sskh:基于pdg的重复代码筛选

       .6.2 算法sslchy:基于pdg的剽窃检测

       .6.3 算法ssmcwpp:整个程序的动态“胎记”

       .7 基于软件度量的分析方法

       .7.1 算法sskk:基于软件度量的重复代码筛选

       .7.2 算法sslm:基于度量的软件作者鉴别

       .8 小结

       ç¬¬ç«  用硬件保护软件

       .1 使用发行的物理设备反盗版

       .1.1 对发行盘片的保护

       .1.2 软件狗和加密锁

       .2 通过可信平台模块完成认证启动

       .2.1 可信启动

       .2.2 产生评估结果

       .2.3 tpm

       .2.4 盘问式验证过程

       .2.5 社会可信性和隐私问题

       .2.6 应用和争议

       .3 加密的可执行文件

       .3.1 xom体系结构

       .3.2 阻止重放攻击

       .3.3 修补有漏洞的地址总线

       .3.4 修补有漏洞的数据总线

       .3.5 讲评

       .4 攻击防篡改设备

       .4.1 监听总线——破解微软的xbox

       .4.2 猜测指令——破解达拉斯半导体公司的dsfp微处理器

       .4.3 破解智能卡

       .4.4 非侵入式攻击

       .4.5 主板级的保护

       .5 小结

       å‚考文献

如何设计好的RESTful API

       å®‰å…¨æ˜¯æ’久的话题,对于基于WSDL和SOAP的Web Service,我们有WS-Security这样的安全规范来指导实现认证、授权、身份管理等安全需求。那么,RESTful API有无成熟可用规范或实现框架呢?如何保证RESTful API的安全性呢?

       å¦‚何对RESTful API进行版本控制,请分享您认为实用的做法?

       HTTP1.1规范中给出的动词对于设计RESTful API够用吗?您在实际项目中会扩展自己的动词吗?在什么情况下需要扩展?

       ä»Šå¹´5月份发布的JAX-RS 2.0规范对于RSTfulAPI的设计最有价值的特性是哪个(些)? 它(们)用于解决什么问题?

       èƒ½å¦ä¸ºInfoQ的读者们推荐一款实用的RESTful API开发框架,并说明您的推介理由。

       HTTP2.0规范正在制定当中,您对它的期待是什么?

       InfoQ:什么是好的RESTful API?相信每个人都有自己的评判标准。那么,您认为一个好的RESTful API应该具有哪些特征呢?

       æŽé”Ÿï¼šä¸€ä¸ªå¥½çš„RESTful API,应该具备以下特征:

       è¿™ä¸ªAPI应该是对浏览器友好的,能够很好地融入Web,而不是与Web格格不入。

       æµè§ˆå™¨æ˜¯æœ€å¸¸è§å’Œæœ€é€šç”¨çš„REST客户端。好的RESTful API应该能够使用浏览器+HTML完成所有的测试(不需要使用编程语言)。这样的API还可以很方便地使用各种自动化的Web功能测试、性能测试工具来做测试。Web前端应用(基于浏览器的RIA应用、移动App等等)也可以很方便地将多个RESTful API的功能组合起来,建造Mashup类的应用。

       è¿™ä¸ªAPI中所包含的资源和对于资源的操作,应该是直观和容易理解的,并且符合HTTP协议的要求。

       REST开发又被称作“面向资源的开发”,这说明对于资源的抽象,是设计RESTful API的核心内容。RESTful API建模的过程与面向对象建模类似,是以名词为核心的。这些名词就是资源,任何可命名的抽象概念都可以定义为一个资源。而HTTP协议并不是一种传输协议,它实际提供了一个操作资源的统一接口。对于资源的任何操作,都应该映射到HTTP的几个有限的方法(常用的有GET/POST/PUT/DELETE四个方法,还有不常用的PATCH/HEAD/OPTIONS方法)上面。所以RESTful API建模的过程,可以看作是具有统一接口约束的面向对象建模过程。

       æŒ‰ç…§HTTP协议的规定,GET方法是安全且幂等的,POST方法是既不安全也不幂等的(可以用来作为所有写操作的通配方法),PUT、DELETE方法都是不安全但幂等的。将对资源的操作合理映射到这四个方法上面,既不过度使用某个方法(例如过度使用GET方法或POST方法),也不添加过多的操作以至于HTTP的四个方法不够用。

       å¦‚果发现资源上的操作过多,以至于HTTP的方法不够用,应该考虑设计出更多的资源。设计出更多资源(以及相应的URI)对于RESTful API来说并没有什么害处。

       è¿™ä¸ªAPI应该是松耦合的。

       RESTful API的设计包括了三个循序渐进、由低到高的层次:资源抽象、统一接口、超文本驱动。正是这三个层次确保了RESTful API的松耦合性。

       å½“设计面向互联网的API时,松耦合变成了一种“必须有”的强需求。紧耦合的API非常脆弱,一旦公布出去,服务器端和客户端都无法持续进化。尤其是服务器端,公布出去的接口根本不敢改,改了之后,几乎所有客户端应用立即无法正常工作。REST这种架构风格就是紧耦合API的解毒剂,这个话题可以谈的很深,这里就不展开了。感兴趣的读者可以参考《REST实战》。

       è¿™ä¸ªAPI中所使用的表述格式应该是常见的通用格式

       åœ¨RESTful API中,对于资源的操作,是通过在服务器端-客户端之间传递资源的表述来间接完成的。资源的表述可以有很多种格式,并且在响应和请求中的资源表述格式也会有所不同。GET/POST响应中的资源表述格式,常见的有HTML、XML、JSON;POST/PUT请求中的资源表述格式,常见的有标准的HTML表单参数、XML、JSON。

       è¿™äº›å¸¸è§è¡¨è¿°æ ¼å¼ï¼Œå¤„理起来非常容易,有大量的框架和库提供支持。所以除非有很合理的要求,通常不需要使用自定义的私有格式。

       ä½¿ç”¨HTTP响应状态代码来表达各种出错情况

       HTTP响应状态代码,是HTTP协议这个统一接口中用来表达出错情况的标准机制。响应状态代码分成两部分:status code和reason phase。两部分都是可定制的,也可以使用标准的status code,只定制reason phase。

       å¦‚果一个所谓的“RESTful API”对于任何请求都返回 OK响应,在响应的消息体中返回出错情况信息,这种做法显然不符合“确保操作语义的可见性”这个REST架构风格的基本要求。

       è¿™ä¸ªAPI应该对于HTTP缓存是友好的

       å……分利用好HTTP缓存是RESTful API可伸缩性的根本。HTTP协议是一个分层的架构,从两端的user agent到origin server之间,可以插入很多中间组件。而在整个HTTP通信链条的很多位置,都可以设置缓存。HTTP协议内建有很好的缓存机制,可以分成过期模型和验证模型两套缓存机制。如果API设计者完全没有考虑过如何利用HTTP缓存,那么这个API的可伸缩性会有很多问题。

       æŽå»ºä¸šï¼šé¦–先说明一下,对REST这个概念,我一般把它理解为REST风格的架构,但是现在实践中最为广泛认知的是HTTP,而它是REST的一个实现,所以RESTful API也可以不太严格的指基于HTTP的API——当然,即使是不严格的时候,API本身也应该力求遵循REST架构风格。

       æˆ‘认为,一个RESTful API最重要的一点应该是——“尽可能少的先验信息”,这一条也同时是我判断一个好的RESTful API的标准。

       æ¯”如HTTP动词,在实践中,大家可能会常常纠结于有效利用 HTTP 动词,但这却并不是特别重要的事情——除非你理解这么做的价值。HTTP 动词最重要的地方在于它是标准阐明了的行为,也就是说,如果我们的“客户端”遵循约定,那么就不必要发明新的动词,也就不必增加“先验信息”;但是,所谓“先验信息”,针对的是客户端——对API来说就是调用者,对于一些企业内部系统,或者一些传统系统,由于“资源”很稳定,对资源的操作也很稳定,这些系统的“调用客户端”不是浏览器而是另一个系统,此时如果强制对应到HTTP动词,反而会变成额外的“先验信息”,这时我就不会太拘泥HTTP动词,自己制定一套动词放在参数中也可以接受——只要动词不变化,这个系统依然是REST风格的。

       å†æ¯”如Response里面的Content-Type,这个有时会被新手忽略,但这其实很重要,因为一般涉及到系统间协同的API,往往不会使用普通的文本,比较常见的是使用json表达复杂结构,而这与通常的缺省理解不同(缺省一般会认为是text/plain和text/html),所以如果在API中忘记用Content-Type进行区分的话,后续对多种类型的客户端接入的支持就会变成陷阱(我们多次遇到过这个问题)。而如果一开始就检查是否增加先验知识(缺省Content-Type为plain或者允许指定Content-Type),那这一困难就可以避免了。

       ä¸é›ªä¸°ï¼šé¦–先,应该正确地使用HTTP的统一接口,比如HTTP的动词,如果不分青红皂白清一色POST那显然还有改进的余地;

       å…¶æ¬¡ï¼Œèµ„源有合适的粒度,可以从三个方面来评判资源的粒度是否合理——网络的效率、表述的大小以及客户端使用时的易用程度;

       æœ€åŽï¼Œæ˜¯è¡¨è¿°çš„设计,除了表述的正文内容,还有其中的URI和链接,这些都是评判一个RESTful API好坏的标准。

       é©¬é’§ï¼šåœ¨æˆ‘看来,一个好的API标准,就是能尽量利用到HTTP协议的特性,将HTTP当成一种转移协议,而不是传输协议。包括但不限于:利用HTTP的各种动词来明确操作;包含有内容协商,可以根据请求头提供的参数选择一个资源最合适的媒体类型、语言、字符集和编码的表现;使用不同的返回代码来描述各种状态。但实际上见到过的很多声称RESTful API,包括国内的和国外的,能符合这些条件的并不多。parse.com提供的API是我见到过的较为不错的RESTful API,可以作为范例参考。

       InfoQ:安全是恒久的话题,对于基于WSDL和SOAP的Web Service,我们有WS-Security这样的安全规范来指导实现认证、授权、身份管理等安全需求。那么,RESTful API有无成熟可用规范或实现框架呢?如何保证RESTful API的安全性呢?

       æŽé”Ÿï¼šä¿è¯RESTful API的安全性,主要包括三大方面:

       a) 对客户端做身份认证

       b) 对敏感的数据做加密,并且防止篡改

       c) 身份认证之后的授权

       å¯¹å®¢æˆ·ç«¯åšèº«ä»½è®¤è¯ï¼Œæœ‰å‡ ç§å¸¸è§çš„做法:

       åœ¨è¯·æ±‚中加签名参数

       ä¸ºæ¯ä¸ªæŽ¥å…¥æ–¹åˆ†é…ä¸€ä¸ªå¯†é’¥ï¼Œå¹¶ä¸”规定一种签名的计算方法。要求接入方的请求中必须加上签名参数。这个做法是最简单的,但是需要确保接入方密钥的安全保存,另外还要注意防范replay攻击。其优点是容易理解与实现,缺点是需要承担安全保存密钥和定期更新密钥的负担,而且不够灵活,更新密钥和升级签名算法很困难。

       ä½¿ç”¨æ ‡å‡†çš„HTTP身份认证机制

       HTTP Basic身份认证安全性较低,必须与HTTPS配合使用。HTTP Digest身份认证可以单独使用,具备中等程度的安全性。

       HTTP Digest身份认证机制还支持插入用户自定义的加密算法,这样可以进一步提高API的安全性。不过插入自定义加密算法在面向互联网的API中用的不是很多。

       è¿™ä¸ªåšæ³•éœ€è¦ç¡®ä¿æŽ¥å…¥æ–¹â€œå®‰å…¨åŸŸ-用户名-密码”三元组信息的安全保存,另外还要注意防范replay攻击。

       ä¼˜ç‚¹ï¼šåŸºäºŽæ ‡å‡†ï¼Œå¾—到了广泛的支持(大量HTTP服务器端、客户端库)。在服务器端做HTTP身份认证的职责可以由Web Server(例如Nginx)、App Server(例如Tomcat)、安全框架(例如Spring Security)来承担,对应用开发者来说是透明的。HTTP身份认证机制(RFC )非常好地体现了“分离关注点”的设计原则,而且保持了操作语义的可见性。

       ç¼ºç‚¹ï¼šè¿™ç±»åŸºäºŽç®€å•ç”¨æˆ·å+密码机制的安全性不可能高于基于非对称密钥的机制(例如数字证书)。

       ä½¿ç”¨OAuth协议做身份认证

       OAuth协议适用于为外部应用授权访问本站资源的情况。其中的加密机制与HTTP Digest身份认证相比,安全性更高。需要注意,OAuth身份认证与HTTP Digest身份认证之间并不是相互取代的关系,它们的适用场景是不同的。OAuth协议更适合于为面向最终用户维度的API提供授权,例如获取隶属于用户的微博信息等等。如果API并不是面向最终用户维度的,例如像七牛云存储这样的存储服务,这并非是OAuth协议的典型适用场景。

       å¯¹æ•æ„Ÿçš„数据做加密,并且防止篡改,常见的做法有:

       éƒ¨ç½²SSL基础设施(即HTTPS),敏感数据的传输全部基于SSL。

       ä»…对部分敏感数据做加密(例如预付费卡的卡号+密码),并加入某种随机数作为加密盐,以防范数据被篡改。

       èº«ä»½è®¤è¯ä¹‹åŽçš„授权,主要是由应用来控制。通常应该实现某种基于角色+用户组的授权机制,这方面的框架有不少(例如Spring Security),不过大多数开发团队还是喜欢自己来实现相关功能。

       æŽå»ºä¸šï¼šæˆ‘不认为安全是RESTful API需要考虑的问题,事实上我觉得这是两个正交的问题。当然,如果使用RESTful API来提供认证、授权和身份管理,那也算是双方有关系,但是这和其它风格的API设计所要考虑的问题似乎没什么区别,不值得特别注意。

       ä½†æ˜¯åœ¨å…·ä½“设计层面,这两者的“正交点”上似乎确实有些问题,因为REST是一个推崇状态无关原则的架构风格,而认证和授权通常基于第三方解决方案,所以往往会出现违背有状态约束的问题,这个地方我也没有特别的想法,当然这个困难和原问题关系不大。

       è‡³äºŽWS-族的协议,我不太了解,不太能参与讨论。

       ä¸é›ªä¸°ï¼šå¯¹äºŽRESTful API,常见的安全措施都是可以继续使用的。例如,为了防篡改,可以对全部参数进行签名;为了防范重放攻击可以在请求中增加一次性的Token,或者短时间内有效的Token;对内容加密可以实现数据防泄露……;对于DDoS攻击,各种HTTP流量清洗策略,都可以继续发挥作用,因为这就是基本的HTTP请求。

       åœ¨æŽˆæƒå’Œè®¤è¯æ–¹é¢ï¼ŒOAuth 2.0已经基本成熟了,并且得到了广泛地应用。如果可以,接入第三方账户体系是个不错的选择,比如Google和Facebook的,国内的当然也有几个候选。

       é©¬é’§ï¼šä¸ªäººè®¤ä¸ºRESTful的安全性分为几个层次,在安全要求较高的场合,可以通过HTTPs这样的加密协议来保证网络层的安全,应用层的安全可以通过OAuth实现认证,而对于资源的访问授权,则只能依靠应用程序来实现了。

       InfoQ:如何对RESTful API进行版本控制,请分享您认为实用的做法?

       æŽé”Ÿï¼šä¸€ä¸ªæ¯”较简单实用的做法是直接在URI中插入版本号,这样做允许多个版本的API并行运行。

       å¦ä¸€ä¸ªåšæ³•æ˜¯åœ¨HTTP请求中加入自定义头信息,标明使用的版本号。不过这个做法其实对浏览器不够友好,简单地使用浏览器+HTML无法测试。

       æŽå»ºä¸šï¼šç›®å‰æ¯”较好的方式还是在uri设计中添加版本信息,其它方法都不如这个实用。

       ä¸é›ªä¸°ï¼šä¸ªäººè®¤ä¸ºæœ€å¥½çš„版本化,就是没有明显的版本。在对已发布的服务进行变更时,要尽量做到兼容,其中包括URI、链接和各种不同的表述的兼容,最关键的就是在扩展时不能破坏现有的客户端。例如,要变更一个参数,可以选择同时兼容新旧两种输入,或者保持老参数不动,提供一个新的参数,在文档中必须做出说明,不推荐新用户再继续使用之前的参数。

       å¦‚果必须要进行不兼容的变更,那么可以选择标记不同的版本号,这时可以选择在路径或参数中增加版本信息。也有做法是增加HTTP标头,只是在调用时会稍有不便,推荐前两种方法。

       é©¬é’§ï¼šRESTfulAPI的版本升级,尽量兼容之前的版本,保证原有的API都能正常工作,可以通过HTTP 转跳到新的资源。另外一种实用的做法就是在url中保留版本号,同时提供多个版本供客户端使用,如 v1.rest.com 或者 rest.com/v1/ 这样。

       InfoQ:HTTP1.1规范中给出的动词对于设计RESTful API够用吗?您在实际项目中会扩展自己的动词吗?在什么情况下需要扩展?

       æŽé”Ÿï¼šè¿™ä¸ªé—®é¢˜å–决于设计者如何看待和设计资源。如果资源抽象做的很好,对于某个资源的任何操作,通常都能够映射到CRUD四个类别中。CRUD四个类别对于操作资源来说,绝大多数情况下是完备的。HTTP的GET/POST/PUT/DELETE四个方法,对于CRUD四个类别的操作来说是足够的,映射关系是Create-POST/Retrieve-GET/Update-PUT/Delete-DELETE。

       æˆ‘们通常不会选择创建自己的动词,这样做对于客户端开发者来说,需要更多的学习成本。如果在资源上定义的操作过多,我们会选择拆分出更多的资源。

       æŽå»ºä¸šï¼šä¸€èˆ¬æ˜¯å¤Ÿç”¨çš„,有时一些“不够用”的场景是由于我们没有设计出合理的资源,比如批量操作。但是,正如之前所说的那样,对于某些内部的、传统的(因此模型稳定且已知)系统,API提供者和调用者会有自已的固定动词表,此时没必要拘泥。另外,我不建议扩展动词,一旦扩展了动词,其实已经破坏了我之前说的*“尽可能少的先验信息”*,那么,扩展动词和重新设计动词的成本差别不大。基于这个考虑,我建议尽可能保持动词不变,除非你想重新设计动词表。

       ä¸é›ªä¸°ï¼šä¸€èˆ¬æƒ…况下,常用的HTTP动词是够用的,并没有出现一定要自己扩展动词的情况。其实,最常用的也就是GET、POST、DELETE和PUT,而HEAD、OPTIONS、TRACE则基本用不太到。如果出现一时找不到合适的动词,安全幂等的操作用GET,其他都可以用POST,在设计资源时稍加考虑即可。

       é©¬é’§ï¼šåœ¨æˆ‘的实际项目中,只用到了POST,PUT,DELETE,GET这四个动词。

       InfoQ:今年5月份发布的JAX-RS 2.0规范对于RSTfulAPI的设计最有价值的特性是哪个(些)? 它(们)用于解决什么问题?

       æŽé”Ÿï¼šREST开发框架RESTEasy项目负责人Bill Burke,去年写了一篇文章介绍JAX-RS 2.0。

       æˆ‘同意Bill在文章中的观点,在JAX-RS 2.0增加的内容中,最重要的三部分为:

       a) Client API——用来规范化JAX-RS客户端的开发方式。

       b) Server-side Asynchronous HTTP——用来实现服务器端推送功能,而不需要依靠低效的轮询方式。

       c) Filters and Interceptors——用来分离关注点,将鉴权、日志等逻辑与业务逻辑分离开,更好地实现代码重用。

       è¿™ä¸‰éƒ¨åˆ†çš„内容对于开发者来说都很有用。遵循JAX-RS规范做开发,可以确保服务器端以及客户端代码的可移植性。

       æŽå»ºä¸šï¼šæˆ‘个人关注异步API这部分,主要是因为流式服务将会越来越多,那将大量需要这类支持。

       InfoQ:能否为InfoQ的读者推荐一款实用的RESTful API开发框架,并说明您的推介理由。

       æŽé”Ÿï¼šè¿™ä¸ªé—®é¢˜æˆ‘就不详细回答了。不同的编程语言有不同的REST开发框架,对于REST的支持程度也不同。开发RESTful API的需求范围很广,可选择的开发框架的范围也很广。保持多样性是繁荣生态环境的基础。像Java就有支持JAX-RS规范的Jersey、RESTEasy、Restlet、Apache CXF,和不支持JAX-RS规范的Spring MVC等等很多框架。这些框架目前都做的不错。我对框架的选择没有倾向性。RESTful API设计的最佳实践应该是通用的,而不是必须依赖某种特定的开发框架。

       æŽå»ºä¸šï¼šä¸å¥½æ„æ€ï¼Œè¿™ä¸ªæˆ‘不太重视,没法推荐,不过我可以解释一下为什么对RESTful API框架不感冒的原因。

       REST作为一个架构风格,对我们的系统开发有很大影响,但是这些影响一般是针对架构(例如状态无关)或者设计(例如资源识别)上的,所以一旦涉及到具体实现,主要工作就基本结束了,此时开发框架能做的事也就只有简化编程了(相较而言,有的框架还能起到引导设计的作用),而由于RESTful会抽象动词,所以实现层面中和API规范相关的工作本来就不多,那么框架的价值就更小了。

       å½“然,我们也不可能直接基于servlet/rakc/wsgi来开发,不过一般的编程语言都会提供一些简单的url route/match策略,我们使用这些就足够了。另外,有些框架能帮我们生成全部的动词支持,但这也未必是好事,我一般倾向于按需实现——用到了再支持,这就更不需要太关注开发框架对RESTful的支持了。

       ä¸é›ªä¸°ï¼šç”±äºŽæœ¬äººæ˜¯Spring的拥护者,工作中也一直在使用Spring,所以在选择框架时会更多地倾向Spring MVC(并不是说别的框架不好,这里有些个人主观的成份)。如果一定要选择其他框架,也要选择能够方便与Spring集成的框架。如果在项目中已经使用了Spring,那么没有什么理由不选择Spring MVC,鉴于目前Spring在各种项目中的高出镜率,相信一般情况下都会选择Spring MVC。

       REST的成熟度模型中,第三层就是HATEOAS,Spring目前还提供了Spring Hateoas子项目,对链接、资源等方面的支持都做了一定的增强。

       é©¬é’§ï¼šæˆ‘目前在实际项目中使用的是Spray,这是一个开源的 REST/HTTP 工具包和底层网络 IO 包,基于 Scala 和 Akka 构建。轻量级、异步、非堵塞、基于 actor 模式、模块化和可测试是Spray的特点。

       InfoQ:HTTP2.0规范正在制定当中,您对它的期待是什么?

       æŽé”Ÿï¼šæˆ‘的期待包括两个方面:应该做的和不应该做的。

       HTTP/2.0规范应该做的:

       ä¸ŽHTTP/1.1协议保持兼容。兼容的含义是说两者可以并存,客户端应用可以根据服务器端的能力,自由地选择使用HTTP/2.0还是HTTP/1.1,而且选择过程对应用来说是透明的。

       æ”¹è¿›HTTP协议(作为资源的统一接口)之中操作语义表达方式的语法,提高网络传输效率。

       æ›´å¥½åœ°æ¨¡å—化,这样HTTP/2.0协议的实现能够更好地模块化。应用程序可根据需要选择适当的模块,而不是要么全有、要么全无。

       åºŸå¼ƒæŽ‰HTTP/1.1协议中一些很少有人用到的部分,例如采用管道(pipelining)方式发送请求。

       å¢žåŠ æ›´å¤šçš„动词,以适应除CRUD之外的其他场景。

       HTTP/2.0规范不应该做的:

       HTTP/2.0协议不应该把底层的数据加密机制(即SSL)作为必选项。

       HTTP/2.0协议不应该背离REST架构风格的约束,尤其是要确保操作语义对于中间组件的可见性。

       åœ¨ä¸Šé¢è¿™ä¸¤ä¸ªæ–¹é¢ï¼ŒRoy Fileidng曾经与SPDY协议设计者Mike Belshe发生过激烈争论,详情请看:Roy Fielding谈Google SPDY协议

       æŽå»ºä¸šï¼šå¯¹æ­¤è§„范关注不多,不知道会不会有对于流的支持,目前我所知道的只有chunk方式进行简单的支持,但是真正的流需要区分数据通道和控制通道——哪怕是逻辑上的区分,这样就直接对REST风格产生了很大冲击,考虑到流式服务在未来的发展潜力,我特别期待业界在这方面有所进展。

       ä¸é›ªä¸°ï¼šHTTP 2.0很大程度上是借鉴了Google的SPDY,就我而言,首先,希望这个规范能做到与HTTP 1.1的兼容,使用者如果只认识1.1,那么2.0能优雅“降级”;其次,希望2.0能带来更好的性能,SPDY在这方面还是有所改进的,希望HTTP 2.0能再接再厉;最后,希望这个规范能在最终定稿时附带一个最佳实践,正确引导人们合理地使用HTTP 2.0。

       é©¬é’§ï¼šæ²¡ç ”究过,估计即使出来,1.1还有很长的生命周期,不会很快被取代。