开放 api 已是大势所趋。而 api 这种东西有个特点就是覆水难收。一旦公开出去了,被大量用户使用,一旦修改,就会让广大用户都掉坑里。所以,api 在设计之初就要尽量考虑周全,并预留扩展可能。

目前绝大多数 api 都是通过 http 协议访问。api 一般有两类,一类只涉及到提供方和使用者,另一类还涉及到最终用户。因此,前一类在认证上也只涉及两方,而后一类还涉及到用户授权,也就是通常使用的 OAuth。这里先说说第一类。比如 amazon aws 的 api、google 的地图 api 等的认证就属于这类。

双方认证的 api 通常的认证方式是使用一组 id 和密钥,用 id 来标记应用,用密钥来对请求做签名。id 和密钥一般是应用向服务方申请的。这样,服务费也可以控制 api 的使用。如果想停止某个用户访问 api,只需要取消这个用户的认证信息。即可。

举个例子,google 地图的 api,就是简单使用密钥对 url 做 HMAC_SHA1 签名。如:

  1. $signature = hash_hmac("sha1",$url_to_sign, $key, true);

然后把签名编码后,追加在 url 后面访问。服务方根据请求中的 id 找到对应的密钥,同样做一遍签名,如果相等则认证通过。对于一些更复杂一些的 api ,请求还可能通过 HTTP header 、post body 来传递。此时,签名就需要把所有关键信息都一起签名。为了避免参数顺序的敏感性,即仅仅改变参数顺序就会影响签名结果,通常还会要求先对参数进行排序。amazon aws 的新版认证协议还对于一些关键参数改为了每次加入一个就签名一次。这恐怕也是因为 sha1 也已经没那么可靠了吧。

这是最简单的认证方式。使用这种方式,由于密钥并没有在网络上传递,hmac sha1 算法也是不可逆的,第三方无法冒充别的用户对自己的 url 进行签名。但是这种简单的方式有个缺点。同样的 url 在签名后是可以反复使用的。因此,如果恰好第三方需要的服务或数据和你的相同,那也可以直接复制你的 url 去用,花你的 money 、读你的数据。这也叫重放攻击。

为了避免或者减少重放攻击的危害,一些 api 把时间也作为了参数之一。签名的时候也把时间一起签进去。在服务端不仅要比较签名,还要请求的时间和服务端时间的差是否在许可范围,比如 15 分钟内。amazon aws 的 api 就是如此。这样,就算截获了一个请求,也顶多在 15 分钟内有效。不过由此带来的问题是,如果时钟偏差大了,就无法正常调用服务了。因此,客户端和服务端都必须严格对时。如在 linux 上开启 ntpd 。另外,对于 15 分钟内的重复攻击,仍然没有很好的办法。这时候,能做的也许就是在业务上减少由此可能带来的损失了。比如对 aws 来说,重复申请资源会因为重名而无法通过,而重复修改或删除资源请求通常也是没意义的。而另一些资源信息,仅在 15 分钟内可以重放,也无法获得新的有价值的数据。

如果真的在意这一点又该如何呢?以上方法都是在保持协议无状态前提下的。如果放弃这个前提,变成有状态协议,就有了别的方法。比如,可以引入一次性令牌来解决。首次访问前,先去请求一个一次性令牌,之后请求服务的签名的时候,把这个令牌也一起签名,并一起传递。服务端会检查该令牌是否仍然有效。请求后,会使原来的令牌失效,同时颁发一个新的一次性令牌。这看着是不是有点眼熟?有点像是 session 的实现方式吧。session 就是在客户端和服务端传递一个令牌来标示身份,在无状态协议中模拟状态的。第三方就算劫持到令牌,因为没有密钥,也没法加以利用。而拦截到的请求在使用一次后,也已经失效。这样就有效避免了重放攻击。但是,这样也是有代价的,如此一来,服务端就必须来维护这些会话。可能会占用大量资源,并有可能由此受到拒绝服务攻击。因此,多数服务都没有采用这种方式来认证。

以上的认证方式只适合用在服务端-服务端。而不适合用在客户度,如浏览器、移动端、桌面客户端等。在这些地方使用双方认证 API ,就不可避免的要把应用的密码携带分发。这是很危险的。一旦有人从中破解获取了你的密钥,一切就全完蛋了。这时候,要通知所有终端更换密钥也是件麻烦事。通常,都需要使用应用自己的服务端作为代理来访问。至少是通过应用自己的服务端来计算签名。但是这对于一些服务,比如云存储,代价就有点大了,这样一来,应用就还是得在自己的服务器上走大量的流量。要解决这样的问题,一些 API 提供方给了另外的一种认知方式。

应用先给自己的每个用户生成一个 uid,然后用密钥对其签名得到用户密钥,把应用 id,uid,签名保存在客户端分发。从客户端发起请求时,带上应用 id,uid,使用用户密钥签名。服务端则用同样的方式验证,并可以通过 uid 来做数据的访问控制。这样一旦客户端被破解,也只会影响一个终端用户,而不是像之前一样,所有用户的信息都收到威胁。

转载: http://xiezhenye.com/2013/03/api-%E5%8F%8C%E6%96%B9%E8%AE%A4%E8%AF%81%E6%8E%A2%E8%AE%A8.html

API 双方认证探讨的更多相关文章

  1. RESTful Api 身份认证中的安全性设计探讨

    REST 是一种软件架构风格.RESTful Api 是基于 HTTP 协议的 Api,是无状态传输.它的核心是将所有的 Api 都理解为一个网络资源.将所有的客户端和服务器的状态转移(动作)封装到 ...

  2. Web APi之认证(Authentication)两种实现方式【二】(十三)

    前言 上一节我们详细讲解了认证及其基本信息,这一节我们通过两种不同方式来实现认证,并且分析如何合理的利用这两种方式,文中涉及到的基础知识,请参看上一篇文中,就不再叙述废话. 序言 对于所谓的认证说到底 ...

  3. RESTful Api 身份认证安全性设计

    REST是一种软件架构风格.RESTful Api 是基于 HTTP 协议的 Api,是无状态传输.它的核心是将所有的 Api 都理解为一个网络资源.将所有的客户端和服务器的状态转移(动作)封装到 H ...

  4. Web APi之认证(Authentication)两种实现方式后续【三】(十五)

    前言 之前一直在找工作中,过程也是令人着实的心塞,最后还是稳定了下来,博客也停止更新快一个月了,学如逆水行舟,不进则退,之前学的东西没怎么用,也忘记了一点,不过至少由于是切身研究,本质以及原理上的脉络 ...

  5. 关于RESTFUL API 安全认证方式的一些总结

    常用认证方式 在之前的文章REST API 安全设计指南与使用 AngularJS & NodeJS 实现基于 token 的认证应用两篇文章中,[译]web权限验证方法说明中也详细介绍,一般 ...

  6. 转 Web APi之认证(Authentication)两种实现方式【二】(十三)

    前言 上一节我们详细讲解了认证及其基本信息,这一节我们通过两种不同方式来实现认证,并且分析如何合理的利用这两种方式,文中涉及到的基础知识,请参看上一篇文中,就不再废叙述废话. 序言 对于所谓的认证说到 ...

  7. Web APi之认证

    Web APi之认证(Authentication)两种实现方式后续[三](十五)   前言 之前一直在找工作中,过程也是令人着实的心塞,最后还是稳定了下来,博客也停止更新快一个月了,学如逆水行舟,不 ...

  8. spring cloud+dotnet core搭建微服务架构:Api授权认证(六)

    前言 这篇文章拖太久了,因为最近实在太忙了,加上这篇文章也非常长,所以花了不少时间,给大家说句抱歉.好,进入正题.目前的项目基本都是前后端分离了,前端分Web,Ios,Android...,后端也基本 ...

  9. spring cloud+.net core搭建微服务架构:Api授权认证(六)

    前言 这篇文章拖太久了,因为最近实在太忙了,加上这篇文章也非常长,所以花了不少时间,给大家说句抱歉.好,进入正题.目前的项目基本都是前后端分离了,前端分Web,Ios,Android...,后端也基本 ...

随机推荐

  1. Python 判断一个字符串是否在列表中任何一个字符串中出现过

    strlist = ['a1', 'a2', 'b1'] if any("a" in s for s in strlist):

  2. 15款Chrome浏览器插件让设计师告别拖延症

    秋高气爽,分享一大波有效帮助设计师提高工作效率的Chrome浏览器扩展程序! 高效是另一种王道 无论是在工作中,还是在生活中,有些词我们说来就满满正能量,而另外一些话提起就很沮丧,后者如拖延症,前者如 ...

  3. glibc下的内存管理

    在解码过程中我们也遇到了类似的问题,第一次解码的音频比较大60s,耗了3G的内存,reset之后内存并没有退还给操作系统,第二次即使解一个10s的音频 几周前我曾提到,我被项目组分配去做了一些探究li ...

  4. MyISAM 和InnoDB区别

    MyISAM 和InnoDB 讲解 InnoDB和MyISAM是许多人在使用MySQL时最常用的两个表类型,这两个表类型各有优劣,视具体应用而定.基本的差别为:MyISAM类型不支持事务处理等高级处理 ...

  5. [C# 基础知识梳理系列]专题六:泛型基础篇——为什么引入泛型

    引言: 前面专题主要介绍了C#1中的2个核心特性——委托和事件,然而在C# 2.0中又引入一个很重要的特性,它就是泛型,大家在平常的操作中肯定会经常碰到并使用它,如果你对于它的一些相关特性还不是很了解 ...

  6. linux包之e2fsprogs之chattr命令

    概述 [root@localhost ~]# rpm -qf /usr/bin/chattre2fsprogs-1.41.12-18.el6.x86_64 chattr命令的作用很大,其中一些功能是由 ...

  7. expression encoder 4 安装 出现“已经安排重启您的计算机

    问题: expression encoder 4  安装 出现“已经安排重启您的计算机 解决的办法,注册表数据的修改 开始 运行 regedit HKEY_LOCAL_MACHINE\SYSTEM\C ...

  8. 【转】3篇:Xilium CefGlue 关于 CLR Object 与 JS 交互类库封装报告:官方原生方法分析

    作者: 牛A与牛C之间 时间: 2013-11-17 分类: 技术文章 | 暂无评论 | 编辑文章 主页 » 技术文章 » 第3篇:Xilium CefGlue 关于 CLR Object 与 JS ...

  9. 【转】用 PHP 内置函数 file_put_contents 写入文件

    PHP 内置函数 file_put_contents 用于写入文件. file_put_contents 函数最简单的写法,可以只用两个参数,一个是文件路径,一个是要写入的内容,语法如下: file_ ...

  10. js键盘事件全面控制

    js键盘事件全面控制 主要分四个部分第一部分:浏览器的按键事件第二部分:兼容浏览器第三部分:代码实现和优化第四部分:总结 第一部分:浏览器的按键事件 用js实现键盘记录,要关注浏览器的三种按键事件类型 ...