认证鉴权也可以如此简单—使用API网关保护你的API安全
随着企业数字化进程的发展,企业正在大量使用 API 来连接服务和传输数据,API 在带来巨大便利的同时也带来了新的安全问题,被攻击的 API 可能导致重要数据泄漏并对企业业务造成毁灭性影响。因此,API 安全正受到业界和学术界的广泛关注。
一、认证鉴权,必须要做的事情
通常来说,API 有两种典型类型 :一种是传统的SOAP API,另一种则是更为流行的RESTful API。
SOAP API使用Web安全性的内置协议(WS),这种协议会定义一套保密和身份验证的规则集,SOAP API支持两大国际标准机构(OASIS和W3C)制定的标准,他们结合使用 XML 加密、XML 签名和 SAML 令牌来验证身份和授权,因此SOAP API 是有 Web 安全性做保障的,但也需要更多的管理成本。
RESTful API通过使用HTTP和JSON进行传输,无需存储,也不需要重新打包数据,它速度很快,因此比较流行。
类比起来,使用RESTful API就像寄明信片,很快就能送达目的地,但明信片上所有的信息都是明文的,大家都能看到,因此会有安全隐患。
认证鉴权,就是保护API的常用方法。在对API分级后,对那些安全性需求较高的API增加认证鉴权机制,就相当于增加了一层访问的屏障。
1.1 什么是认证鉴权?
简单来讲,认证鉴权的本质就是——判断用户是否具备能够操作某种资源的权限。
具体来讲,这里包括了一些关键问题:
- 认证(
Authentication
):系统如何正确分辨出操作用户的真实身份? - 授权(
Authorization
):系统如何控制一个用户该看到哪些数据、能操作哪些功能? - 凭证(
Credential
):系统如何保证它与用户之间的承诺是双方当时真实意图的体现,是准确、完整且不可抵赖的? - 保密(
Confidentiality
):系统如何保证敏感数据无法被包括系统管理员在内的内外部人员所窃取、滥用? - 传输(
Transport Security
):系统如何保证通过网络传输的信息无法被第三方窃听、篡改和冒充? - 验证(
Verification
):系统如何确保提交到每项服务中的数据是合乎规则的,不会对系统稳定性、数据一致性、正确性产生风险?
1.2 认证鉴权的主要方式
常用的认证方式包括:Basic认证(基本认证)、Digest认证(摘要认证)、App Secret Key + HMAC、JWT认证、OAuth2认证。
1. Basic认证
HTTP Basic 是一个非常传统的API认证技术,也是一个比较简单的技术。
主要思路:
- 将username和password使用冒号(:)拼起来
- 使用base64编码
- 将编码后的字符串放在HTTP头Authorization中,发送给服务端。
WWW-Authenticate: Basic Realm='xxxx'
- 服务端验证请求头,认证通过,返回200, 认证不通过,返回401。
问题:base64不是加密协议,因此相当于用户名密码在网络上明文传输,有密码泄露的风险。
2. Digest认证
Digest Access,指“HTTP摘要认证“。在Basic认证的基础上,增加了:1. 请求方需要对用户名、密码和域进行md5传输,保证不明文。2. 增加了随机数(nonce)和 qop(quality of protection),保证md5不固定。
主要思路:
- 调用方发起一个普通的HTTP请求。
- 服务端返回401错误,并且在HTTP头里的
WWW-Authenticate
返回如下信息:
WWW-Authenticate: Digest realm="testrealm@host.com",
qop="auth,auth-int",
nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093",
opaque="5ccc069c403ebaf9f0171e9517f40e41"
其中,nonce为服务端生成的随机数。
- 客户端进行MD5计算。
HA1 = MD5(username:realm:password) // 服务端算法为MD5
HA1 = MD5(MD5(username:realm:password):nonce:cnonce) // 服务端算法为MD5-sess,其中nouce为服务端随机数,cnonce为客户端随机数
HA2 = MD5(method:digestURI) //qop为'auth'
HA2 = MD5(method:digestURI:MD5(entityBody)) //qop为'auth-int'
response = MD5(HA1:nonce:HA2) //qop为'auth'
response = MD5(HA1:nonce:nonceCount:cnonce:qop:HA2) //qop为'auth-int'
- 将编码后的字符串放在HTTP头Authorization中,发送给服务端。
GET /dir/index.html HTTP/1.0
Host: localhost
Authorization: Digest username="Mufasa",
realm="testrealm@host.com",
nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093",
uri="/dir/index.html",
qop=auth,
nc=00000001,
cnonce="0a4f113b",
response="6629fae49393a05397450978507c4ef1",
opaque="5ccc069c403ebaf9f0171e9517f40e41"
- 服务端验证请求头,认证通过,返回200, 认证不通过,返回401。
问题:容易受到中间人攻击。服务器可以存储HA1,如果HA1被泄露,攻击者可以直接访问API内容。
3. App Secret Key + HMAC
这种方式的主要特征有 1)引入App Secret Key来标识API调用者身份,2)引入HMAC防止消息被篡改。
HMAC:为了防止消息在传递过程中被篡改,可以引入MAC( Message Authentication Code),这是一种给消息签名的技术。在实现中,首先对消息进行MAC,得到一个摘要字串。接收方得到消息后,进行同样的计算,然后比较这两个MAC字符串,如果一致,则表明没有被修改过。而HMAC( Hash-based Authenticsation Code),指的是,利用Hash技术完成这一过程,比如使用SHA-256算法。
- RP发送一个认证请求给OP;
- OP对EU进行身份认证,然后提供授权;
- OP把ID Token和Access Token(需要的话)返回给RP;
- RP使用Access Token发送一个请求UserInfo EndPoint;
- UserInfo EndPoint返回EU的Claims,即用户信息。
其中,第2步中,OP对EU的认证是通过OAuth2.0来做的,因此也可以使用基于Authorization Code的认证方式。
基于Authorization Code的认证方式
这种方式使用OAuth2的Authorization Code的方式来完成用户身份认证,所有的Token都是通过Token EndPoint来发放的。
1. RP发送请求给OP,请求授权码。一个例子如下:
GET /authorize?
response_type=code
&scope=openid%20profile%20email
&client_id=s6BhdRkqt3
&state=af0ifjsldkj
&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb HTTP/1.1
Host: server.example.com
2. OP接收到认证请求之后,需要对请求参数做严格的验证,验证通过后引导EU进行身份认证并且同意授权。完成后,会重定向到RP指定的回调地址,并且把code和state参数传递过去。比如:
HTTP/1.1 302 Found
Location: https://client.example.org/cb?code=SplxlOBeZQQYbYS6WxSbIA&state=af0ifjsldkj
3. RP使用上一步获得的code来请求Token EndPoint,这一步同OAuth2。然后Token EndPoint会返回响应的Token,其中除了OAuth2规定的部分数据外,还会附加一个id_token的字段。id_token字段就是上面提到的ID Token。例如:
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache
{
"access\\_token": "SlAV32hkKG",
"token_type": "Bearer",
"refresh_token": "8xLOxBtZp8",
"expires_in": 3600,
"id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjFlOWdkazcifQ.ewogImlzc
yI6ICJodHRwOi8vc2VydmVyLmV4YW1wbGUuY29tIiwKICJzdWIiOiAiMjQ4Mjg5
NzYxMDAxIiwKICJhdWQiOiAiczZCaGRSa3F0MyIsCiAibm9uY2UiOiAibi0wUzZ
fV3pBMk1qIiwKICJleHAiOiAxMzExMjgxOTcwLAogImlhdCI6IDEzMTEyODA5Nz
AKfQ.ggW8hZ1EuVLuxNuuIJKX_V8a_OMXzR0EHR9R6jgdqrOOF4daGU96Sr_P6q
Jp6IcmD3HP99Obi1PRs-cwh3LO-p146waJ8IhehcwL7F09JdijmBqkvPeB2T9CJ
NqeGpe-gccMg4vfKjkM8FcGvnzZUN4_KSP0aAp1tOJ1zZwgjxqGByKHiOtX7Tpd
QyHE5lcMiKPXfEIQILVq0pc_E2DzL7emopWoaoZTF_m0_N0YzFC6g6EJbOEoRoS
K5hoDalrcvRYLSrQAZZKflyuVCyixEoV9GfNQC3_osjzw2PAithfubEEBLuVVk4
XUVrWOLrLl0nx7RkKU8NXNHq-rvKMzqg"
}
4. RP拿到这些信息之后,需要对id_token以及access_token的有效性进行验证。具体验证规则参考:https://openid.net/specs/openid-connect-core-1_0.html
二、保护API安全,API网关做了什么
腾讯云API网关作为接入层,保护API安全是它理所当然的责任。目前,API网关支持的认证鉴权方式包括:应用认证、OAuth2.0认证和EIAM认证。
2.1 应用认证
API网关应用认证采用App Secret Key + HMAC方式。客户端在调用 API 时,需要使用签名密钥对请求内容进行签名计算,并将签名同步传输给服务器端进行签名验证。
解决方案特点:
EIAM+API 网关解决方案,是通过API网关现有的OAuth2.0认证方式与EIAM集成的,底层基于OICD(OAuth2.0)协议。
不同于API网关的OAuth2.0方式,新的方式有如下特点:
- 可一键创建授权 API 和业务 API,轻配置;
- EIAM 维护用户目录,免自建认证服务器;
- 在认证能力基础上支持鉴权功能,保护 API 安全;
- EIAM 内置多种 RBAC 模型,免自建鉴权服务器和授权模型;
- 内置缓存机制,更快的访问速度;
具体来说,
1) 传统的OAuth2.0方式在创建授权API时需要填写较多参数,同时需要建立授权API与业务API的绑定关系,EIAM方式只需要最多4个参数,即可一键创建授权API和业务API。
2)传统的OAuth2.0方式需要自己实现颁发和校验Token的服务,EIAM方式可将该部分逻辑托管到EIAM上。
3)传统的OAuth2.0方式只会校验ID token的有效性,更细粒度的权限校验需要用户自己解开token进行,EIAM方式提供了用户可选的鉴权功能,API网关会结合EIAM对请求来源进行权限校验,对于未授权的用户,返回403,“Access not authorized”,表明用户没有通过鉴权。对于完成授权的用户,直接返回 API 后端调用结果。
4)传统的OAuth2.0方式用户需要自己维护授权关系,EIAM方式下,可将用户RBAC模型托管到EIAM上。
5)传统的OAuth2.0方式每次都要请求授权API和业务API,EIAM方式下,会优先使用本地鉴权方式,减少网络传输带来的时延,同时,会对授权资源列表进行缓存,在一定时间范围内实现更快速的访问。
具体流程:
使用 EIAM 认证方式,只需要三步:
- 创建认证方式为“EIAM 认证”的 API。
- 在 EIAM 中创建用户池和用户,并进行授权。
- 使用用户凭证调用 API 网关 API。
具体配置方法可参考https://cloud.tencent.com/document/product/628/59669
适用场景:
- 不想自建认证服务器或授权模型
- 希望业务快速接入OAuth2.0协议保护API安全
- 具有较细粒度鉴权需求
四、我们是怎么做到的?
4.1 技术架构
API网关EIAM认证提供多种选项:
1) 提供两种认证与鉴权方式:“只认证不鉴权”与“既认证又鉴权”:
- 选择“只认证不鉴权”方式,请求授权 API 时,API 网关将校验传入的用户访问凭证,认证通过后,颁发 id_token。使用 id_token 请求业务 API 时,API 网关将检验 id_token 的合法性,校验通过后转发给业务后端。
- 选择“既认证又鉴权”方式,请求授权 API 时,API 网关将校验传入的用户访问凭证,认证通过后,颁发 id_token。使用 id_token 请求业务 API 时,API 网关将检验 id_token 的合法性,同时校验访问用户是否具有访问该 API 的权限,API 网关将只放行具有访问权限的用户请求。用户与资源的授权关系可在EIAM进行配置。
2) 提供两种应用类型:“非 Web 客户端”与“Web 客户端”:
- 非 Web 客户端:适用于非 Web 客户端发起的API调用,如服务器端、C/S架构系统客户端、App 客户端、小程序客户端,能支持以 POST 方式发起请求,需要自行请求授权 API 获取 Token,再使用 Token 请求业务 API;
- Web 客户端:适用于 Web 客户端发起的 API 调用,如浏览器、客户端应用 Web Viewer 等 Web 客户端,能支持以 Web 重定向方式接收返回信息。
针对不同配置,实现方案如下:
4.2 技术方案
1) 云API网关应用
EIAM支持多种协议类型的“应用”,可用于身份认证、单点登录等场景。
在API网关EIAM认证方式中,EIAM定制了”云API网关“类型应用,采用OAuth2+JWT作为API认证、授权的协议实现。由OAuth2串联用户认证流程,JWT Token带出用户身份、权限信息。
2)资源级授权
EIAM提供应用级授权、资源级授权功能。其中,资源级授权是指,基于RBAC访问模型,将应用下的指定资源授权予指定的授权对象。
在API网关EIAM认证方式中,API网关的一个API,对应EIAM应用下的一个资源,支持用户、用户组和组织机构对该资源的权限管理。一个API网关API,可以绑定多个EIAM应用,作为应用下的一个授权资源。
3)认证方式
基于OAuth2.0协议,EIAM提供授权码模式和密码模式两种模式进行认证。当API网关EIAM应用类型为"非Web客户端"时,使用密码模式,当API网关EIAM应用类型为"Web客户端"时,使用授权码模式,
4)鉴权方式
EIAM提供在线鉴权接口,API网关可以提供<应用id、用户Id、服务Id、API Id>信息来判断用户是否有权限访问该服务下的API。
为了优化性能,EIAM在返回id_token时,会将该用户具备访问权限的资源列表写入JWT 的 scope字段进行返回。API网关将该资源列表进行缓存,在之后的访问中使用本地鉴权方式,实现更快的鉴权。
五、未来,更简单更安全
保护API安全,是API网关作为接入层重要的能力,除了认证鉴权,API网关还提供了更多方式来保护API安全。他们包括:
- 链路加密
- 请求映射与转换;
- 参数校验;
- IP 访问控制;
- 跨域访问控制 CORS;
- 流量监控与保护;
- DDoS 防护能力;
- 与 Web 应用防火墙 WAF 结合;
欢迎访问API网关官网文档 https://cloud.tencent.com/document/product/628 或咨询相关同学进行了解。
在未来,我们也会致力于提供更多方式和更简单的配置,来保护API网关上API的安全性。
参考文献
https://openid.net/specs/openid-connect-core-1_0.html
https://www.cnblogs.com/lishiqi-blog/p/11164961.html