所有文章 > API安全 > 给初学者的RESTful API 安全设计指南!
给初学者的RESTful API 安全设计指南!

给初学者的RESTful API 安全设计指南!

RESTful API已经是在线开放API实施上的标准,企业API开放平台大多都会采用RESTful API做为实施标准。面向开放的互联网提供API接口,API安全性就是企业必须面对的一个问题,解决API安全要从API设计的第一步开始,而不是上线之后打补丁式的后置解决方案,不但会引发严重的API安全漏洞,且导致用户体验差、品牌口碑变坏。

在开启API安全设计之前,需要了解以下基本知识,会有助于初学者快速上手。

  • API是什么?
  • RESTful API是什么?
  • 开放API一般使用哪种 API描述规范?
  • 常见的 API安全漏洞有哪些?

结合各路大神的API安全解决方案及个人经验,以下几种方式比较适合初学者。

1、身份认证设计

身份认证包含很多种,有HTTP Basic,HTTP Digest,API KEY,Oauth,JWK等方式,下面简单讲解下:

1.1 HTTP Basic

REST由于是无状态的传输,所以每一次请求都得带上身份认证信息,身份认证的方式,身份认证的方式有很多种,第一种便是http basic,这种方式在客户端要求简单,在服务端实现也非常简单,只需简单配置apache等web服务器即可实现,所以对于简单的服务来说还是挺方便的。但是这种方式安全性较低,就是简单的将用户名和密码base64编码放到header中。

base64编码前:Basic admin:admin

base64编码后:Basic YWRtaW46YWRtaW4=

放到Header中:Authorization: Basic YWRtaW46YWRtaW4=

正是因为是简单的base64编码存储,切记切记在这种方式下一定得注意使用ssl,不然就是裸奔了。 在某些产品中也是基于这种类似方式,只是没有使用apache的basic机制,而是自己写了认证框架,原理还是一样的,在一次请求中base64解码Authorization字段,再和认证信息做校验。很显然这种方式有问题,认证信息相当于明文传输,另外也没有防暴力破解功能。

1.2 API KEY

API Key就是经过用户身份认证之后服务端给客户端分配一个API Key,类似:http://example.com/api?key=dfkaj134,一般的处理流程如下: 一个简单的设计示例如下: client端:

server端:

client端向服务端注册,服务端给客户端发送响应的api_key以及security_key,注意保存不要泄露,然后客户端根据api_key,secrity_key,timestrap,rest_uri采用hmacsha256算法得到一个hash值sign,构造途中的url发送给服务端。 服务端收到该请求后,首先验证api_key,是否存在,存在则获取该api_key的security_key,接着验证timestrap是否超过时间限制,可依据系统成而定,这样就防止了部分重放攻击,途中的rest_api是从url获取的为/rest/v1/interface/eth0,最后计算sign值,完之后和url中的sign值做校验。这样的设计就防止了数据被篡改。 通过这种API Key的设计方式加了时间戳防止了部分重放,加了校验,防止了数据被篡改,同时避免了传输用户名和密码,当然了也会有一定的开销。

1.3 Oauth2

OAuth2 协议适用于为外部应用授权访问本站资源的情况。其中的加密机制与HTTP Digest身份认证相比,安全性更高。使用和配置都比较复杂,这里就不涉及了。

1.4 JWT

JWT 是JSON Web Token,用于发送可通过数字签名和认证的东西,它包含一个紧凑的,URL安全的JSON对象,服务端可通过解析该值来验证是否有操作权限,是否过期等安全性检查。由于其紧凑的特点,可放在url中或者 HTTP Authorization头中,具体的算法就如下图

2、授权设计

份认证之后就是授权,根据不同的身份,授予不同的访问权限。比如admin用户,普通用户,auditor用户都是不同的身份。简单的示例:

$roles  =  array(
'ADMIN'=>array(
'permit'=>array('/^((\/system\/(clouds|device)$/'), // 允许访问哪些URL的正则表达式
'deny'=>array('/^(\/system\/audit)$/') // 禁止访问哪些URL的正则表达式
),

'AUDIT'=>array(
'permit'=>array('/^(\/system\/audit)$/'),//允许访问的URL正则表达式
'deny'=>array('/^((\/system\/(clouds|device).*)$/')
)
);

上述是垂直权限的处理,如果遇到了平行权限的问题,如用户A获取用户B的身份信息或者更改其他用户信息,对于这些敏感数据接口都需要加上对用户的判断,这一步一般都在具体的逻辑实现中实现。

3、URL过滤设计

在进入逻辑处理之前,加入对URL的参数过滤,如

/site/{num}/policy

限定num位置为整数等,如果不是参数则直接返回非法参数,设定一个url清单,不在不在url清单中的请求直接拒绝,这样能防止开发中的api泄露。

此处的设计原则与RESTful API设计原则中的URL命名规则一致。

4、加密传输

优先使用SSSL确保链路安全。

报文内容二次加密,隐私性低的可以采用对称秘钥,隐私性高且防止抵赖需求采用证书模式的非对称加密。

5、速率限制

请求速率限制,根据api_key或者用户来判断某段时间的请求次数,将该数据更新到内存数据库(redis,memcached),达到最大数即不接受该用户的请求,同时这样还可以利用到内存数据库key在特定时间自动过期的特性。例如:在返回时设置X-Rate-Limit-Reset:当前时间段剩余秒数,APC的示例代码如下:

Route::filter('api.limit',  function()
{
$key = sprintf('api:%s', Auth::user()->api_key);
// Create the key if it doesn't exist
Cache::add($key, 0, 60);
// Increment by 1
$count = Cache::increment($key);
// Fail if hourly requests exceeded
if ($count > Config::get('api.requests_per_hour'))
{
App::abort(403, 'Hourly request limit exceeded');
}
});

6、使用HTTP状态码做为错误处理

对于非法的,导致系统出错的等请求都进行记录,一些重要的操作,如登录,注册等都通过日志接口输出展示。有一个统一的出错接口,对于400系列和500系列的错误都有相应的错误码和相关消息提示,如401:未授权;403:已经鉴权,但是没有相应权限。如不识别的url:

{"result":"Invalid URL!"}

错误的请求参数

{"result":"json format error"}

不允许的方法:

{"result":"Method Not Allowed"}

非法参数等。上面所说的都是单状态码,同时还有多状态码,表示部分成功,部分字符非法等。示例如下:

HTTP/1.1  207  Multi-Status
Content-Type: application/json; charset="UTF-8"
Content-Length: XXXX
{
"OPT_STATUS": 207
"DATA": {
"IP_ADDRESS": [{
"INTERFACE": "eth0",
"IP_LIST":[{
"IP": "192.168.1.1",
"MASK": "255.255.0.0",
"MULTI_STATUS": 200,
"MULTI_RESULT": "created successfully"
},{
"IP": "192.167.1.1",
"MASK": "255.255.0.0",
"MULTI_STATUS": 409,
"MULTI_RESULT": "invalid parameter"
}]
}]
},

7、隐私数据做不透明处理

隐私数据避免通过接口传输,如果必须传递,那么要做不透明处理,如果需要使用原始值,那么必须加密处理。

API设计指南系列


RESTful API设计概要
RESTful API 状态码设计指南
RESTful API 设计检查清单
高质量的API文档能够提升API安全性
加强阅读:19个API安全最佳实践 
RESTful API常见问题清单

转载来源:https://www.kancloud.cn/kancloud/rest-api-design-safety

#你可能也喜欢这些API文章!