在这两年接触的项目基本上是基于前后端分离、多种后端服务组合而成的,这有别于先前的“单体”的项目,而且我们还需要考虑外部应用接入的场景、用户-服务的鉴权、服务-服务的鉴权等多种鉴权场景。
本方案基于客户端Token与网关结合的方式。所有的客户端请求都经过网关,网关将校验客户端发送上来的Token等信息,如果通过则转发给对应的服务,如果不通过则直接返回40X给客户端。
架构
- 获得authorize,用户/设备从UAA Service中获得authorize信息
- 附加mac token,请求在访问服务时候附加上mac token
- Gateway进行认证,Gateway将收到的每个mac token发送给UAA Service进行校验
- 每个服务只有权限去操作自己负责的那部分功能(待规划)
流程
- 用户/客户端从UAA Service中获得Token
- 如果UAA Service中无此用户/客户端,则抛出AuthorizationException异常并返回401
- 如果UAA Service认证成功,返回对应的Token信息
- 用户的请求数据,请求头Authorization中带上Token信息
- 网关过滤所有的请求,携带Token、请求信息向UAA Service请求鉴权
- 如果UAA Service鉴权失败,抛出AuthenticationException异常并返回403
- 如果UAA Service鉴权成功,返回用户的权限等信息
- 网关向业务发起请求(此时,不携带授权信息。因为鉴权等都在网关处理了)
- 业务服务向微服务发起请求,同样也不携带授权信息
- 返回结果给用户
协议
根据开发阶段的鉴权、用户-服务的鉴权、服务-服务的鉴权等不同的场景,定义了三种方式的协议。
Debug Token协议
debug token适用于在开发测试环境调试API。
协议
在Client发出api请求之前,必须将debug token的信息放在HTTP Header的Authorization里面。
|
|
上面的代码中:
userid为调试的用户
realm为可选字段,预定为用户所在的领域(应用、行业或者机构)
示例(伪代码)
|
|
Mac Token协议
mac token适用于不安全网络下的API授权
协议
通过“登录接口”可以获得Token。mac_token的数据结构如下:
|
|
hmac算法见:[[https://tools.ietf.org/html/rfc2104]]
在Client发出api请求之前,必须将mac token的信息放在HTTP Header的Authorization里面。
上面的代码中:
id为mac_token.access_token
nonce为 时间戳:随机码(客户端生成),有效时间+-5分钟
mac为请求签名: mac=base64(hmac(mac_token.mac_key,mac_token.mac_algorithm,request_content))
request_content = nonce + \n + http-method + \n + request-url + \n + host + \n
http-method,请求的方法,大写,如:GET
request-url,请求的地址(包含参数的部分,不包含域名部分),区分大小写,如/v0.1/databases
host,为HTTP Header中的host,区分大小写,如dynamax.io
示例(伪代码)
获得token
request
reqponse
访问资源
|
|
Bearer Token协议
bearer token适用于安全网络下的api授权。也就是说,bearer适用于微服务之间的相互调用的api授权。
协议
可以通过“bearer_token”的接口获得相应的bearer_token,数据结构如下:
|
|
在Client发出api请求之前,必须将bearer token的信息放在HTTP Header的Authorization里面。
|
|
上面的代码中:
“XXX123XXXXX”为bearer_token.access_token
user_id可选,该值位获得bearer token对应的账号。该值用来传递用户信息到其他服务端,用来判断是否有权限。
待优化的点
- 怎么鉴定一个请求是否需要认证?白名单?
- 各个业务服务以及微服务是否需要再次认证?会不会出现绕过网关的情况?
- 所有的服务都通过网关,在UAA Service中进行鉴权,会不会造成UAA Service是个瓶颈点?
- 是否能够很方便地扩展到OAuth2?