如何构建和设计以确保 API 的安全性
如何构建和设计以确保 API 的安全性
面对常见的OWASP十大威胁、未经授权的访问、拒绝服务攻击、以及窃取机密数据等类型的攻击,企业需要使用通用的安全框架,来保护其REST API,并保证良好的用户使用体验。本文向您介绍四种类型的API安全保护方式。
管理好API安全性 API的安全性涉及到各种端到端的数据保护,它们依次包括:来自客户端的请求经由网络到达服务器/后端,由服务器/后端发送相应的响应,响应横跨网络,最后到达客户端,这一系列的过程。因此,API的安全性可以大致分为如下四种不同的类别,我们将逐一进行详细讨论:
(1)传输中的数据安全
· 保护客户端与API网关之间的动态数据
· 保护API网关与后端服务之间的动态数据
(2)访问控制与抵御拒绝服务(DoS)攻击
(3)身份验证与授权:使用OAuth2.0或OpenID Connect,来可靠地识别最终用户的信息
(4)数据保密与屏蔽个人身份信息(Personally Identifiable Information,PII) 1. 传输中的数据安全 对于所有公共且不受保护的API来说,我们必须用到TLS。如今随着硬件的进步,TLS的实施开销几乎可以忽略不计了,而且随着延迟在逐渐减小,越来越多的最终用户会处于安全考虑而选用TLS。总的说来,TLS具有如下主要特点:
· TLS应当在北向(northbound)和南向(southbound)端点同时实施。
· 应确保使用TLS的最新版本,并对客户端、API网关和目标后端予以支持。
· 证书密钥、以及信任凭证的存储都应该受到高度保护和加密。
· 只有经过授权的用户才能访问证书密钥、以及信任凭证。 2. 访问控制与抵御拒绝服务(DoS)攻击
(1) 网络级别的防御:如果API网关被托管在云端,则需要使用由云服务商所提供的 DDoS防御机制,例如:由Apigee(Google)所运营的Apigee Edge托管云平台、 GCP(Google云平台)和AWS(Amazon Web),它们都提供了网络级别的DDoS防御。
(2) 内容交付网络:像Akamai、Neustar和Rackspace之类的CDN,都可以用于缓解那些对于API的DDoS攻击。
(3) “僵尸”检测:如今各大API管理平台都已经针对僵尸/机器人类型的攻击,推出了检测API流量,识别各种恶意/非必要请求,并生成警报/阻止恶意请求到达的API网关服务。例如:Apigee(Google)提供了一种称为“Apigee Sense”的检测服务。它是一种智能数据驱动的API安全产品,它可以通过自动识别各种可疑的API客户端行为,以提供额外的保护层。同时,管理员也可以在此基础上通过纠正性措施,来保证用户的体验度,以及后端系统的安全性。
(4) 策略执行:我们应该在位于API客户端和客户后端之间的API代理上,通过强制实施各种策略,以严格管控合法用户对于API的访问。如下策略能够在一定程度上保护API免受恶意黑客的攻击:
· API速率限制:通过限速,我们可以减少大量导致拒绝服务的API请求,并抑制暴力攻击和服务滥用。特别是在API代理服务器上,我们可以采用如下限速的机制:
· 基于应用程序或个别API予以限速,以保证每个API或应用程序只能按照固定的请求数配额,去访问对应的服务。
· 基于GET或POST请求予以限速,当然具体的请求数设定,可以根据不同时段的GET或POST量而有所不同。
(5) 正则表达式保护:应当根据预定义的正则表达式(如DELETE、UPDATE和EXECUTE)来评估入栈请求的URI路径、查询参数、包头、表格参数、变量、XML有效负载、以及JSON负载。任何匹配上了预定义表达式的请求都将被视为威胁,并被立即拒绝掉。请参阅OWASP top 10(https://www.owasp.org/index.php/Category:OWASP_Top_Ten_Project#OWASP_Top_10_for_2013),以了解具体有关要如何验证正则表达式的信息。
(6) JSON输入验证:对于PUT/POST/DELETE之类请求的负载,我们应执行JSON验证,以通过指定对于各种JSON结构的限制(如最大深度、对象的最大数量、最长字符串长度的名称、以及数组中所允许的最大元素数等),来最小化可能受到的攻击面。
(7) XML输入验证:应当对PUT/POSTE/DELETE之类请求的负载执行XML验证。具体可使用如下方法来根据配置的限制,以检测XML负载的各类攻击、以及监控针对XML的威胁:
· 根据XML的架构(.xsd)来验证消息
· 根据特定黑名单里的关键字与模式,来评估消息内容 · 在分析消息之前,检测出已损坏或格式错误的消息
(8) 验证请求 · 验证输入HTTP动词:适当地对那些允许类动词做出限制,而对于其他所有动词,则返回相应的响应代码(如:“403禁止错误”)。
· 验证包头:应当根据API所支持的功能,显式地验证“内容类型”、“接受”和“内容长度”等包头。此外,还应该执行针对强制性包头(如:授权、以及特定类型的API包头)的验证。
· 验证入栈内容类型:对于PUT/POST/DELETE之类入栈请求的内容类型(例如:应用/XML或应用/JSON)、以及内容类型的包头值进行验证。对于缺少内容类型的包头、或异常内容类型的包头,应当直接拒绝,并返回“406不可接受”的响应内容。
· 验证响应类型:不要简单地将“接受”包头复制到响应内容类型的包头中。如果“接受”包头中并没有明确地包含允许的类型,应当直接拒绝该请求,并返回“406不可接受”的响应内容。
· 处置不支持的资源:适当通过限制资源,只开放可供调用的资源;而对于其他所有未实现的资源,则应返回“未知资源”之类相应的响应代码。
(9) 访问控制:通过配置策略,只允许来自特定IP地址、域名或区域的请求。而那些未通过此类条件的请求,应当被网关直接拒绝掉。
3. 身份验证和授权 通常情况下,身份验证和授权是同步发生的。
· 身份验证常被用于识别最终用户。
· 授权则被用于授予已识别用户访问某些资源的权限。 在API领域中,OAuth和OpenID Connect是最为常用的机制。它们通过利用现有的IAM架构,并以交换访问令牌的方式,来验证用户的身份,进而保护API的各个端点。通过OAuth和OpenID Connect,我们不需要每次都构建单独的系统,以存储用户名和密码的方式,来匹配用户可以访问的API资源。
OAuth OAuth通常采用不透明(OPAQUE)令牌,来实现委托访问(Delegated Access)的目的。OAuth2.0授权框架使得第三方应用能够获得对于HTTP服务的有限访问权限。通常,用户不应当为了访问某些存储在第三方的受保护数据,而在公网上传输自己的密码。而OAuth恰好能够为用户访问自己的数据,提供了信任凭据的安全保护。
OAuth不是一种身份验证协议,而是授权协议。由于身份验证通常发生在颁发访问令牌之前,因此我们很容易理解为在接受访问令牌时,也进行了身份验证。然而,仅凭拥有访问令牌,并不能证明用户的身份。在OAuth中,令牌被设计为对客户端来说是不透明的,客户端仅能从令牌中获取权限信息,而不会涉及到用户名与密码。
不透明令牌:在许多的具体实现中,OAuth2.0会返回OPAQUE字符串,用以换取被称为访问令牌的用户凭据,而这些令牌将被进一步用于访问各种API的资源。不透明令牌并非用来存储用户身份标识与信息,而是指向了某个数据库里的具体数据项。例如:我们可以用Redis来存储各种键-值(key-value)。而Cassandra之类的NoSQL数据库则非常适合利用内存中的哈希表,根据I/O来查找有效负载。由于用户角色是直接从数据库中被读出的,因此我们可以通过更改后端的角色,来传递并展现给用户。
OpenID Connect OpenID Connect采用ID令牌和访问令牌,来实现用户识别与委托访问。OpenID Connect是进行用户身份验证的标准。由于直接构建在OAuth2.0之上,因此在大多数情况下,OpenID Connect是与OAuth架构一起被部署的。在交付形式上,它还为客户端提供OpenID Connect令牌。该身份令牌是一个已签名的JSON Web令牌(JWT),它与常规的OAuth访问令牌一起被提交给客户端应用程序。
· JSON Web令牌:JWT令牌实际上是一个完整的JSON对象。它经历了base64编码之后,使用对称共享密钥、或公/私钥的方式进行签名。JWT可以包含诸如:主题、user_id、令牌颁发时间、以及过期时间等信息。通过密钥签名,它可以确保只对拥有授权访问密钥的系统才能生成令牌。不过值得注意的是,系统在对JWT进行签名时,JWT通常不会被加密(当然,您也可以选择对其进行加密)。那么,这就意味着任何拥有令牌访问权限的人都可以读取令牌里的数据。因此,业界的最佳实践是:只把用户标识(如user_id)放在令牌中,而不是个人身份信息(如电子邮件或社会保障号码)。此外,它们应当通过TLS之类的加密通道来进行传递。
· JWT限制:鉴于日常对于用户的禁用、以及添加或删除角色往往需要一段时间才能同步生效,而且由于令牌存储在客户端,即使我们在数据库中对其所颁发的JWT用户进行了禁用标记的话,也无法直接让该令牌及时无效。虽然JWT采取了预定义到期的机制,但是用户仍然需要等待到期。显然这会影响到用户的服务架构,特别是那些电商类的应用。
当然,业界也提供了一些变通的方法。例如:您可以使用带有令牌或user_id的黑名单,但是这需要向数据库引入新的认证机制。因此,一种推荐的方法是:通过黑名单以确保每个令牌都带有一个JTI声明(或带有一个存储在数据库中的JWT Id)。因此,只要您希望注销的令牌数量远小于应用程序中的用户数量,那么操作起来就非常灵活。
可见,对于那些拥有管理员、项目所有者、服务客户经理等多种角色的企业应用来说,切换用户的不同角色并不会对JWT立即生效。例如:管理员修改了某个授权用户的角色,那么只要他不去刷新JWT,也就无法获悉该变更。
下面是OpenID Connect的三种实现用例:
· 出栈方向的Web单一登录(SSO):向企业用户提供对于SaaS应用、以及合作伙伴应用的访问管控,但并不公开本企业的用户名与密码。
· 入栈方向的Web单一登录:允许社交账号/第三方登录,但无需存储外部用户与密码。
· 实现各种本地应用的原生单一登录。
OAuth和OpenID Connect都支持OAuth2规范所指定的四种授权类型,下图描述了其中一种授权流程图。API开发人员可以根据手头项目所需的约束与实现方案,来选用不同的授权类型。
4. 数据保密与屏蔽个人身份信息 众所周知,由于密码、安全令牌和API密钥包含了不同程度的内部信息,它们不应该出现在URL中,或者被Web服务器的日志所捕获。此外,诸如UserID、密码、帐号、信用卡号码等个人身份信息,也应该处于“被打码”的状态,哪怕是在交易和审计日志中。
公共API的安全实践 由于独立于任何用户,因此公共API的设计初衷就是为了公开各种非敏感、以及只读的数据(例如天气类API),当然也就不必添加任何身份验证与授权环节。不过,我建议您通过如下的方面,来打造能够应对各种威胁与滥用的API:
· 在IP地址级别上应用速率限制的相关策略。
· 使用API密钥验证的方式。通过存储在网关上的方式,保证API的密钥不会被公布给任何客户端。因此,当拒绝服务攻击使用无效密钥访问API、或是在其他策略已无法阻断黑客攻击时,API密钥验证方式能够有效地发挥作用。
· 采用配额策略(单个或多种配额机制),来实现API的使用限制。
· 如果API被用于特定地理区域的服务器进行通信,那么就应当在地理级别上(县/区等)采取IP地址的筛选。
· 开发人员应尽量采用一次性注册的方式,并使用自己的API密钥去调用API。
结论
在企业内部、以及企业之间需要集成不同的应用时,开发人员能够通过API来快速且方便地予以实现。不过,如果没有恰当地保护好API,那么就会让整个企业面临各种风险与威胁。因此,我们需要在开发和实施之前,就对API的安全性进行良好的构建和设计,从而提高企业的整体安全态势。
如何构建和设计以确保 API 的安全性的更多相关文章
- 如何设计提高服务API的安全性(一)基础介绍
场景 现今越来越多公司提供了Sass平台服务,大部分也直接提供API.如快递鸟.微信Api.云服务.如何保证这些服务的安全性是一门重要的课题.如快递跟踪.机票查询等很便捷地影响着我们d的生活,对这些技 ...
- 如何设计提高服务API的安全性(二)API密钥方式详解
在上文已经讲述了基础介绍,这篇文章详细讲解API密钥方式. 利用何种加密方式呢? 经过上面加密算法的理解,单向加密不仅性能高,而且有压缩性,即长度一致,有效减少网络传输过程中的字节大小.适合我们这种调 ...
- 前阿里P8架构师谈如何设计优秀的API
随着大数据.公共平台等互联网技术的日益成熟,API接口的重要性日益凸显,从公司的角度来看,API可以算作是公司一笔巨大的资产,公共API可以捕获用户.为公司做出许多贡献.对于个人来说,只要你编程,你就 ...
- 如何设计优秀的API(转)
到目前为止,已经负责API接近两年了,这两年中发现现有的API存在的问题越来越多,但很多API一旦发布后就不再能修改了,即时升级和维护是必须的.一旦API发生变化,就可能对相关的调用者带来巨大的代价, ...
- Chris Richardson微服务翻译:构建微服务之使用API网关
Chris Richardson 微服务系列翻译全7篇链接: 微服务介绍 构建微服务之使用API网关(本文) 构建微服务之微服务架构的进程通讯 微服务架构中的服务发现 微服务之事件驱动的数据管理 微服 ...
- 如何设计好的RESTful API之安全性
保证RESTful API的安全性,主要包括三大方面: a) 对客户端做身份认证 b) 对敏感的数据做加密,并且防止篡改 c) 身份认证之后的授权 1.对客户端做身份认证,有几种常见的做法: 1)在请 ...
- 如何为非常不确定的行为(如并发)设计安全的 API,使用这些 API 时如何确保安全
原文:如何为非常不确定的行为(如并发)设计安全的 API,使用这些 API 时如何确保安全 .NET 中提供了一些线程安全的类型,如 ConcurrentDictionary<TKey, TVa ...
- Atitit.论图片类型 垃圾文件的识别与清理 流程与设计原则 与api概要设计 v2 pbj
Atitit.论图片类型 垃圾文件的识别与清理 流程与设计原则 与api概要设计 v2 pbj 1. 俩个问题::识别垃圾文件与清理策略1 2. 如何识别垃圾图片1 2.1. 体积过小文件<1 ...
- Html5 Egret游戏开发 成语大挑战(六)游戏界面构建和设计
本篇将主要讲解游戏界面的构建和设计,会应用到egret.eui的自定义组件,可以很直观的构建一个游戏整体,这里我们仍然只需要使用EgretWing就可以达到目的,本篇可能是篇幅最少的一个,但是涉及自定 ...
随机推荐
- 编码GBK和GB2312、Unicode、UTF-8
一.编码GBK和GB2312 随着计算机发展,各国已经不满足于单纯用ASCII码: 对于我们来说能在计算机中显示中文字符是至关重要的,所以我们还需要一张关于中文和数字对应的关系表: 一个字节8位二进制 ...
- 从命令行配置 Windows 防火墙
从命令行配置 Windows 防火墙 高级用户可以使用命令行来配置 Windows 防火墙.您可以使用 netsh 命令行工具来进行配置. 下表中的 netsh 命令可用于 Microsoft Win ...
- 0208如何利用federated配置远程的数据库和本地数据相互交互
-- 第一步修改本地数据库的配置文件,让其支持federated存储引擎,在[mysqld]配置文件下面增加federated[注意不能写成大写]-- federated -- 第二步创建一个数据库, ...
- 基于java注解实现自己的orm框架
ORM即Object Relation Mapping,Object就是对象,Relation就是关系数据库,Mapping映射,就是说Java中的对象和关系数据库中的表存在一种对应关系. 现在常见的 ...
- jdbc 读取oracle long raw 字段,里面存的是文本
jdbc 读取oracle long raw 字段,里面存的是文本 参考: http://singlewolf.iteye.com/blog/278769 http://blog.csdn.net/r ...
- Fitnesse中的symbols和variables
1.symbols 主要在表间传递信息,作用于一个page中,类似于局部变量 SaveRecordInDatabase name date =key? Bob today bobKey Bill la ...
- ios设计一部WindowsPhone手机
ios设计一部WindowsPhone手机 main.m #import <Foundation/Foundation.h> #import "WindowsPhone.h&qu ...
- iOS 块的简单理解
占位 自己主动转载器那小子,你转完了没? 转完了,我开写了哈! Block,就两个事儿,一个是引用,一个是实例,除了实现处.其他地方都是引用. 以此思路.再继续看看引用和实现的定义方式吧. 參考官方文 ...
- CSU 1506 Problem D: Double Shortest Paths(最小费用最大流)
题意:2个人从1走到n,假设一条路第一次走则是价值di,假设第二次还走这条路则须要价值di+ai,要你输出2个人到达终点的最小价值! 太水了!一条边建2次就OK了.第一次价值为di,第二次为ai+di ...
- js中简单操作
去空格:ss.replace(/\s/g,""); 数组: 千万不能用in操作符 in 是说存不存在这个key而不是value! var a = [66,99,77]; 66 in ...