开放api设计

来源:互联网 发布:博纳文图拉数据 编辑:程序博客网 时间:2024/05/18 14:12

前言

博主不大擅长写作,但看了《高效能程序员的修炼》一书,不得不改变下自己。本文是对最近使用web service做项目时,讨论的总结。如有错误,欢迎勘正,共同提高。第一次写技术博客,难免逻辑和条理不清,也请指点。本着分享和学习的目的,欢迎拍砖!

主要分次三部分:
- Restful风格
- 开放api的技术要点
- 验签


Restful风格

传统的web服务,是在http基础上,通过SOAP和WSDL协议封装的分布式可重用组件。在概念上是基于操作的,所以服务通常用动词命名。与之相比较,Restful并不是一种技术,它是一种架构风格,在概念上它是针对资源的。资源及其状态转变可以呈现/展现(HATEOAS),这些是Restful的核心。作为http协议的主要设计者,Roy Thomas Feilding指出了人们对http协议的滥用,同时自然的利用HTTP协议原本含意来阐述 Restful Web服务。所以首先Restful Web服务是轻量级的,因其直接基于Http协议的,另外还必须符合Restful风格。这里就不再对如何使用Http动词使用作介绍了。博主觉得Resftul的难点在资源URI设计。

开放api的技术要求

资源保护

如何保护资源只供受信任的用户访问。这和正常的交互式应用一样。一般都会给受信任方发放凭证。由于web服务要求访问是无状态的。常见的实现方式有三种:
1)每次访问都验证身份:这种方式需要每次提供凭证,首先服务器验证凭证,通过后进行业务处理。
2)但最常见的每次验证做法是使用密钥验签。这种做法将身份验证和防篡改一起做掉了。方法简单,对技术要求少(不需要https),也不用直接传送凭证,所以这种方式也很流行。
3)第一次访问时,做一次登录以生成Token,以后使用该Token请求服务,博主认为这种做法应该是趋势。首先只需要一次验证;其次符合责任单一的原则;最后用Token代替每次传送凭证提高安全性,即使被劫持也可以随时清理Token(是否有点勉强?)。当然这种做法最好用https,以防登录时凭证被盗取。

防篡改

防止数据在从客户端提交到服务器过程中被篡改是交互设计必须考虑的。现在基本上已经有比较一致的方法就是通过验签来保证。

防敏感信息泄露

对敏感信息的保护(如用户个人信息,财产信息等等)应该是各种开放api必须考虑的。但目前国内在这一块的重视程度远远不够。这个可以在传送过程中对数据加密来完成,通常使用https来达到。

防重放攻击

重放攻击是利用原有的合法请求来破坏开放资源或者客户端服务器连接关系,也有两种方法:
1) 一般请求上传都会带时间戳,可以通过对时间戳的判断解决,比如超过5分钟,则请求无效。这种做法简单而且高效,但不能避免短时间内的多次重放攻击
2) 客户端为每次请求生成唯一序列号,服务器首先验证该序列号的请求是否被处理。如果没有则处理请求并记录该序列号对应请求处理完成;有则忽略该请求。这种方法代价稍高,但可以不受重放攻击。

验签

现在来介绍下在做验签时的考虑。验签原来是被设计来防止信息篡改。首先在一次请求中,客户端通过将一些业务数据加上验签密钥作为输入,采用信息摘要算法(如MD5,SHA1等)计算出验签码,再将这些业务数据和验签码随请求一起发送至服务器端。在服务器端,使用同样的方法计算验签码,并将之与从客户端发送上来的验签码相比较,如果一致则表示业务数据没有被篡改。

传统的面向操作的Web服务,基本上会将业务数据全部放入查询参数或者请求体中,所以可以很容易的在正式业务处理之前做统一验签。这也是很合理,因为验签是技术性的,非业务相关的。这也使得很多非Restful Web服务(像支付宝接口),可以很自然地设计出统一验签方法。

而在Restful方式下,情况稍微复杂些,因为资源URI内包含了业务相关数据;而且每个资源当动词不一样时业务处理也是不一样的;此外不同资源的URI内包含的业务数据及其个数也是不一样的。也就是说,URI和动词已经变成了业务的一部分。另外,还很有可能某些信息既出现在URI中,也出现在请求体中;这也导致出另一个问题,信息不一致时如何处理。那么在这样的情况下,又如何来做验签呢?而且是统一验签,并在验签之前不涉及业务处理。参考了很多开放接口,目前可能还是仁者见仁,还没有一致的看法。看见过以下3种做法:
1)将资源URI和动词忽略,只对请求参数和请求体做验签。这种方法假设主要业务信息都在请求参数和请求体中,并且动词不会被篡改。这种做法还是存在质疑的。
2)只对URL和动词做验签,忽略请求体。这种方法假设URL中已经包含所有业务相关的参数信息,URL不会变(经过load balance和反向代理);此外请求体中不包含额外的关键业务参数。这种做法和前面一样同样让人质疑。
3)对URL和动词以及请求体全部做验签。这种方法假设URL,动词和请求体三者互补的构成业务处理所需的参数信息。做法1)和2)都是在不一致时取某一个为准,验签前不做校验。而这种方法假设只要验签通过,数据不会存在不一致的情况。这种假设也是比较合理的。使用这种方法时要求资源使用方,确保信息不冲突,最好做到信息是正交的。另外需要注意的是,在有Load balance和反向代理的情况下,URL不能发生实质性的改变而影响验签。


总结一下:个人倾向于使用Https+Token +完部验签的方式做开放api的开放

0 0
原创粉丝点击