aaashun's site

home

一种web service api授权设计

30 Mar 2014

这段时间在设计web service api的安全授权机制, 目前给每个应用分配了appId和secretKey, 主要考虑两种情况: 1. 防篡改, 2. 防止重复请求

我们来先看一下目前常见的两种授权方式.

微信的授权方式

所有接口都是使用https协议

access_token是公众号的全局唯一票据,公众号调用各接口时都需使用accesstoken。正常情况下accesstoken有效期为7200秒,重复获取将导致上次获取的access_token失效

获取access token

request: HTTP GET https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
response: {"access_token": "ACCESS_TOKEN", "expires_in": 7200} 

调用其它接口时需带上access_token参数

注意: 由于使用了https, 接口就简单多了, secret可以直接作为参数, 不用担心被监听或中间人攻击的问题

二、盛大云的授权方式

所有接口都是使用http协议, 需对每个请求作签名

使用HMAC(k, m) = H((k XOR opad) + H((k XOR ipad) + m)), http://www.ietf.org/rfc/rfc2104.txt

HMAC较常用的朴素的hash算法H(k + m)更安全

签名过程如下:

1.构造待签名的utf-8字符串

m = HTTPVerb + "\n" + host + "\n" + uri + "\n" + querystring

2.计算签名值

d = HMAC(k, m)
    k是SecretKAccessKey
    m是上面的待签名的utf-8字符串
    d是签名值

3.示例

SndaAccessKeyId: DRINDPIN54JTQWCG3ZJS70QYW
SecretAccessKey: NWYxMDhmOTctMjYyMS00NTI3LWJhODQtMTM2MDBjODlmM2Ji

例如

*请求

http://api.ku6vms.com/video?Title=my-video&SndaAccessKeyId=DRINDPIN54JTQWCG3ZJS70QYW&Timestamp=2014-01-07T00%3A00%3A00&Expires=2014-01-07T00%3A01%3A00&Signature=xxxxxx&SignatureMethod=HmacSHA256

*响应

<CreateVideoResponse>
  <requestId>514e1127-7f6a-4b72-af72-efff59f65b62</requestId>
  <sid>1363519061820</sid>
  <vid>170698</vid>
  <uploadUrl>http://58.215.38.23/vmsUpload.htm</uploadUrl>
</CreateVideoResponse>

AWS与盛大云的授权机制是一样的, 连参数名都是一样的, 见using query api, signature version 2

但是目前AWS用的是https, 盛大云还是http, 导致盛大云的接口授权机制是有问题的, 不能解决上边提到的请求重复发送问题和中间人篡改.

针对重复发送问题可以在AUTHPARAMS里加一个AuthId, AuthId是全局唯一的一个ID, 这样服务端就可以区分不同请求了

针对中间人篡改的问题, 可以把http content也作为HMAC待签名数据的一部分, 即m = querystring + content(费这么多事不如直接上https)

综述

如果有条件使用https, 则推荐类似微信的授权机制, 否则退而求其次使用类似盛大云的改进的接口授权机制.

comments powered by Disqus