百家饭平台作为一个OpenAPI的编辑、测试、代码生成的工具,写了这么多文章,还没有真正介绍过OpenAPI这个标准,正好vuepress写的差不多了。今天就以这个为选题,开始这个月的写作。如果没有特殊声明,介绍的OpenAPI标准以v3.1.0版本为主。
这个月陆续接到多个API网关的需求,百家饭平台也开始扩展原来的网关功能,向企业级API网关挺进,其中,有需求提到对多种API认证方式的需求,那我们就来介绍一下API常用的认证手段和OpenAPI写进标准的都有哪些。
HTTP Basic认证(OpenAPI包含)
Basic认证的基本方法是在头部附加包含用户名和密码的认证信息,形态如下:
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
根据标准(rfc2617)的说明,内容部分的Basic表明这一认证手段是HTTP Basic的认知方式,而后面空格后面的内容是base64加密之后的用户id,:号,密码拼接好的字符串,用伪代码说,也就是
base64(userid+":"+password)
该模式在中间有Proxy存在的时候,存在server和proxy之间的附加交互。
有些语言的http类库都提供直接设置basic认知的函数,比如golang的http.Request类提供BasicAuth来获取认知信息,以及SetBasicAuth用于设置认知信息。(Java搜索了一下好像没有,参考头部信息的设置流程获取即可)。
安全点评
从上面的说明可以看出,这个安全方式的问题是比较明显的,用户名密码虽然经过了base64编码,但是由于base64随意可解,这就导致用户名密码很容易被破解。
因此,使用上述认知手段,建议:
1)一定不要用http,要用https(防止网络监听)
2)考虑对用户名,密码进行加密,不要直接传输用户名、密码,改为传输经SHA1、HMAC等加密方式加密的密文
OpenAPI定义方式
type: http
scheme: basic
Bearer认证
bearer百度了一下,翻译过来是持票人(什么鬼?,就是跑腿的呗),和Basic认证一样,使用了头部的Authorization用来存储认证信息,但是改为:
Authorization: Bearer QWxhZGRpbjpvcGVuIHNlc2FtZQ==
跑腿认证,来源于OAuth2,有标准RFC 6750: The OAuth 2.0 Authorization Framework: Bearer Token Usage (rfc-editor.org)
基本的意思就是服务器在认证了一个用户是有效的之后(比如通过登录接口),在header中附加一个自己加密的信息给回到客户端,客户端拿到这个信息之后,可以在后续调用中附加这一字段,用于加密接口的认证。注意,上面的例子虽然是base64字符串,但是Bearer认证并不要求一定使用base64,实际更多可能是HEX编码的16进制字符串。
这里还要提到,常说的JWT认证实质是Bearer认证的一种,只不过JWT认证明确提到服务器加密的信息应该是JSON的。
安全点评
- 仅可用于HTTPS,还是有泄露问题
- 建议加密的信息中包含时间戳,这样可以基于时间戳做时长控制
这种方式如果是简单的要求调用前获取TOKEN,并不太适用API系统,API系统不应该存在前置的这个认证获取调用过程,所以才有OAuth那套时间控制机制(刷新/重新获取)作为补充。
OpenAPI定义方式
type: http
scheme: bearer
bearerFormat: JWT //如果是JWT可附加该信息,该信息对客户端意义不大,客户端只能获得加密数据
API Key认证
API Key认证方式比较简单,就是在Header、Query或者Cookie中附加特定的访问Key即可,如果你愿意,放在Url Path中都行。
但是这只是一种通用的描述,这种模式描述的范围比较广泛,其内部应该可以分为多种子模式。
附加明文Key
服务器分配一个key给调用方,调用方直接附加这个值用于认证。这种方式简单粗暴,一旦泄露,即可被重复使用,等同于Basic认证。
附加服务器可解密的密文信息
等同于Bearer认证,服务器先生成一个Token再交予客户端,如果使用了Cookie作为存储,其实就是一般的客户端登录机制了。
附加按一定规则生成的密文
在常见的企业对企业的API认证中,经常出现的认证方式,要求客户端根据提交的某个关键信息、实现分配的客户端ID,通常还有时间戳,基于一定的组合方式提交一个MD5或其他算法生成的一串密文。
最常见的就是各种md5,md5一般带secret加请求信息,比如加入一个sign参数,取值为
sign = md5(arg1+'+'+arg2+'+'+timestamp+'+'+secret)
再把userid、sign和明文的arg1、arg2和时间戳一起传给服务器,服务器拿出该user的secret后再拼接出这个sign,比较之后就算通过。(上面字符串形态的+用于避免其中有空内容的情况)
OpenAPI定义方式
apiKey:
type: apiKey
in: header
name: X-API-KEY
上面定义了一个在header中的名为 X-API-KEY的apiKey,OpenAPI虽然完成了字段的定义,但是对字段内容如何生成,并没有相应的标准化方式,这块是OpenAPI没有覆盖到的地方(百家饭提供了公式化参数用于说明如何计算获得key)。
Oauth2认证
Oauth2是10年代,各大主流网站设计第三方应用时设计的一套鉴权机制,核心是通过设计一套独立于用户密码,由登陆后用户生成的密钥以及对应的应用获取、刷新、重置等机制构建的第三方应用登录机制。
打个比分,原来用于必须本人拿信用卡去商家买东西,现在要支持一个小弟去买,那用户从商家拿到一个令牌,发给一个小弟,这个小弟拿着这个令牌就可以代替用户去商家取货,但是这个令牌不是一直有效的,每隔一段小时间要去刷新一下,要是小时间不刷新就要在一个大时间周期里去重新获取。
Oauth2在发展过程中又细分出很多中细的方案,试图覆盖更多的使用场景,上面讲的这个例子是其中的Authorization code模式,另外还有:
- Implicit:简单版Authorization code,不能刷新,只能通过浏览器维持登录。类似用户和小弟都去商场,用户坐沙发上不动弹,小弟到处跑,但是卖家随时可以通过示意用户去获得同意。
- Resource owner password credentials (or just password) – 等同于直接把用户在信用卡密码给小弟
- Client Credentials :小弟有自己的附属卡
感觉后面两种说了跟没说差不多……
OpenAPI定义方式
type: oauth2
description:
flows: //定义oauth2的流程类型和适用的范围
implicit:
authorizationUrl: https://api.example.com/oauth2/authorize
scopes:
read_pets: read your pets
write_pets: modify pets in your account
认证总结
经过这一调研,总结如下表,我们建议Basic就最好别用了,Bearer以及Oauth2看场景,如果你是要给第三方应用开放数据,可以使用。如果你是一个API提供方,面向的对象多是其他企业的下游服务,我建议还是使用复杂API Key认证模式。
存储于HTTP Authorization存储于其他位置附加其他过程控制机制应用建议提交明文HTTP Basic认证简单API Key认证最好不要用提交由服务器加密和解密的密文HTTP Bearer认证带状态控制的API Key认证Oauth2用于第三方应用场景提交客户端加密,由服务器根据内容可验证的密文复杂API Key认证用于服务器对服务器场景
而对于OpenAPI来说,OpenAPI基本已经涵盖了接口常用的三种认证方式的定义,从说明一个API的角度还是够了,下一步需要加强的是生成方式等的定义。
版权归原作者 百家饭OpenAPI 所有, 如有侵权,请联系我们删除。