RESTful接口签名认证实现机制

时间:2020-12-07 14:28:23

RESTful接口

       互联网发展至今,催生出了很多丰富多彩的应用,极大地调动了人们对这些应用的使用热情。但同时也为互联网应用带来了严峻的考验。具体体现在以下几个方面:

1.     部署方式的改变:当用户量不多的情况下,可能只需部署一台服务器就可以解决问题,但是当很多用户的情况下,为抗住高并发访问,需要组成应用集群对外提供服务;

2.     应用构建的改变:很多应用采用了多种技术解决方案,不同编程语言(如C,Java,Python),所以很难采用传统应用构建模式将不同模块整合进来;

3.     数据开放的改变:开放是互联网发展的必然,因为这种方式将应用本身的价值最大化了,同时用户可以基于已有功能生成特有需求应用,提高用户粘度,开放共赢。

而近观传统的Web应用,均为采用集中部署结构,基于某种特定技术开发完成,基于session或cookie等会话追踪机制。加上需要系统间交互信息,使得实现十分复杂,且可伸缩性、易用性、维护性极差。

       基于以上矛盾,出现了一种新的互联网应用架构风格—REST(Representational StateTransfer)。最初这种思路出现在Roy Fielding博士的论文中,他也是HTTP规范的主要作者之一。REST充分利用HTTP的优势,以资源位核心,将资源的CRUD映射为HTTP的 GET PUT POST DELTE方法,服务端无需保存任何客户端信息。客户端的每次资源请求包含了服务端响应需要的所有语义信息。

       我们可以看出,基于REST风格架构的应用特点是:互联网可以看成一个巨大的状态机,资源相当于状态,而URI相当于状态的表述。客户端通过访问不同资源,进行状态切换。服务端却无须记住这些状态,可通过横向扩展方式消除性能瓶颈。

       但是,REST构建的应用如何进行安全控制呢?我们可不希望把自己暴露出去任人“宰割”。目前,常用的方式是OAUTH形式认证方式,这种方式适合对** 应用系统有很强依赖的时候考虑,比如新浪微博开放接口就采用这种。本文主要讲解基于token机制的签名认证模式。

具体签名规则

       在用户可以使用REST接口之前,首先需要通过向REST接口开放方申请,当获准后会收到两个key:accessKey和secretKey。其中 accessKey相当于用户标识,应用会通过它区分不同用户,而secreKey相当于提供给用户的密码,在接口使用过程中都不会在网络中传输,只有用 户和应用系统知道。

       用户对接口的每一次请求都会默认通过某种机制生成一个签名,然后发送给REST服务端。服务端收到后,会根据该机制验证该请求的合法性,从而避免非法用户的随意使用。

       一般,签名以如下形式保存在HTTP Header中发送给REST服务器(其中oss为固定字,Signature是摘要内容):

token = “oss” + “ ”+ accessKey + “:” + Signature

计算的伪代码如下:

StringToSing =HTTP-Verb +”\n”+      //http请求的动作
            Content-MD5+”\n”+     //http请求的MD5值
            Content-Type+”\n”+     //http请求的类型
            Date+”\n”+            //http请求时间
            CanonicalizdResource;  //http请求资源

其中HTTP-Verb是http请求动作,对应于GET,PUT,DELETE,POST等(不能为空),Content-MD5表示请求内容数据的 MD5值(可以为空,以空字符代替,下同),Content-Type为请求的类型(可以为空),Date为本次操作的时间(不能为 空),CanonicalizdResource表示请求的资源(不能为空),当然我们还可以根据系统本身情况指定某些可选或必选参数。

Signature =BASE64(HMAC-SHA1(UTF-8-Encoding-Of(secretKey, StringToSign)))

采用utf-8提前对参数进行编码,可以减少客户端编码差异带来的影响,因为服务端到时是统一采用utf-8来做的,HMAC-SHA1生成签名摘 要指纹信息是不可逆的,安全性得到提高,最后还进行了BASE64编码的原因是将摘要内容全部转换为可显字符,应对某些不可显字符在网络传输中的丢失。

  服务端验证方式则是根据传输过来的token解析出accessKey和Singature,根据accessKey得到本地保存的对应 secretKey(注意其并未在网络中传输),然后再重新根据客户端Signature生成方式重新生成与解析的进行比较,相同则认证成功结束,否则, 直接返回错误信息给客户端。

  整个流程通过以下一张图,进一步阐述:

RESTful接口签名认证实现机制

值得注意的是,JDK提供了java.securty包,里面有各种加密算法,用来进行代码的标识和身份认证。

术语解释

       接下来简要的对常用的摘要算法及加密算法进行解释,方便具体使用过程中采取不同方式加强系统的安全性。

       常用的哈希算法(生成指纹或签名)有MD5和SHA。MD5在文件完整性、网站登录和数字签名等领域有着广泛使用,理论上说MD5数字签名可以伪造,但说其已被破解,那只是杞人忧天罢了。SHA也是著名的哈希算法,不可逆算法,多用于数字签名的情况。

       常用的对称加密算法有DES和AES。DES是老牌的加密算法,这是应用最广泛的密钥系统,也是可逆的对称加密算法。而AES是一种高级的加密标准,2002年成为标准,可用于替代DES,可逆对称加密算法。

       常用的非对称公钥加密算法是RSA,多数网银采用的就是RSA算法来认证的。RSA的安全性依赖于大数的因子分解,它是第一个技能用于数据加密也能用于数字签名的算法,也是可逆算法。但是注意这种算法运算代价很高,速度比较慢,比DES之类算法要慢得多。

       对于RSA啰嗦下,公钥和私钥成对出现。用公钥加密数据,用私钥解密数据(别人传数据给我);用私钥加密数据作为数字签名,用公钥来验证数字签名(我传数据给别人)。