转载本文需注明出处:微信公众号EAWorld,违者必究。
名词解释说明应用即应用程序,本文中特指一个微服务应用业务系统即传统意义上的软件系统,如:OA办公系统、个贷系统等。微服务架构中,业务系统不是个业务逻辑概念,一个业务系统由一个或多个应用(微服务)组成。网关即API Gateway 是客户端访问应用的入口,后端应用的API门户。通常负责身份认证、API管理、路由、编排等等服务即API,特指程序接口 ,如服务调用 即为 API调用。需注意在本文中不要与微服务、应用等概念混淆认证管理系统认证管理系统(IAM),负责身份识别和访问管理,其核心业务是应用系统的访问者的注册、账号密码凭证、访问者基本信息的管理和对已注册的访问者进行合法性认证和访问授权。授权服务指身份认证授权服务,在微服务架构中,通常是认证管理系统(IAM)的一个应用。认证中心具备读取"访问者"身份信息的权限。负责核实"访问者"的身份、为访问者颁发授权码、访问令牌等能力访问者在安全领域统称"Principal",指应用程序功能UI或API的使用者,包含两类:1,基于登录的客户端 2,API 客户端API客户端API Client 即客户端程序类型的访问者,这类客户端自身具备部分API的访问权限,不需要用户授予其访问权限。基于登录的客户端Login-based Client ,用户访问服务提供者的应用程序的功能时,需要通过一个客户端交互界面来与服务提供者交互,用户需要先登录,然后由客户端代表用户身份去访问服务提供者应用程序。
图中星号*标注的位置就是服务调用过程中安全访问过程中的一些需要认证鉴权的关键位置,如:内外部访问认证、令牌验证与授权、内外网通信协议等。后续章节将对这部分展开分析。
基于用户登录的客户端(Login-based Client):用户访问服务提供者的应用程序的功能时,需要通过一个客户端交互界面来与服务提供者交互,用户需要先登录,然后由客户端代表用户身份去访问服务提供者应用程序。
API 客户端(API Client):客户端程序类型的访问者,这类客户端自身具备部分API的访问权限,不需要用户授予其访问权限。
资源所有者
能够许可对受保护资源的访问权限的实体。当资源所有者是个人时,它被称为最终用户。
资源服务器
托管受保护资源的服务器,能够接收和响应使用访问令牌对受保护资源的请求。
客户端
使用资源所有者的授权代表资源所有者发起对受保护资源的请求的应用程序。术语“客户端”并非特指任何特定的的实现特点(例如:应用程序是否是在服务器、台式机或其他设备上执行)。
授权服务器
在成功验证资源所有者且获得授权后颁发访问令牌给客户端的服务器。
对于前面提到的API 客户端,自身具备API访问权,不需要用户授权,因此在OAuth角色对应时,它既是客户端又是资源所有者。
微服务架构中Web应用一般采用前后端分离的模式,前端为基于浏览器访问的纯前端应用,网关作为应用程序的入口,此时网关本身可以代表OAuth中的客户端身份访问服务提供端应用的功能接口。
在微服务架构中,负责颁发访问令牌的授权服务通常在IAM系统中实现
资源服务器,在微服务架构中,所有的业务系统中的服务功能提供者都是资源服务器,也包括IAM系统的账号、组织机构服务、资源权限管理服务等等
2.1 API客户端作为访问者,使用客户端凭证许可
(A) API客户端与授权服务器IAM进行身份验证并请求访问令牌。
(B) 授权服务器IAM对API客户端进行身份验证,如果有效,颁发访问令牌。客户端存储访问令牌,在后 续的请求过程中使用。如果令牌过期或失效或需要重复此流程再次申请访问令牌。
此类应用通常不具备与用户交互的UI,无需用户授权,具备保证客户端凭证安全的能力
此类应用后端需要具备通过https访问授权服务器的能力
此类应用或设备需要具备存储Access Token的能力
2.2 基于登录的客户端作为访问者,使用授权码许可
本场景以微服务架构中常见的前后端分离Web应用作为示例,前端是单页应用,网关作为Web后台是服务提供端应用功能入口,也可作为OAuth2.0的客户端,让前端Web应用能借助网关实现授权码交换。因此在微服务架构中,即便是纯前端单页应用类的Web应用,仍可以用基于网关交互的授权码模式获取访问令牌。其他非前后端分离的混合Web应用自身就是客户端,不需要借助网关交换访问令牌。
(A) 网关通过引导浏览器开始流程授权流程,重定向到统一认证中心的登录页面。
(B)用户输入密码登录,授权服务器验证用户身份,并确认用户是否授权网关的访问请求。
(C)用户授权后,认证中心根据之前网关注册时提供的回调地址,引导浏览器重定向回到网关。重定向URI包含授权码
(D)网关通过包含上一步中收到的授权码和网关自身凭证从授权服务器IAM的请求访问令牌。
(E)授权服务器IAM对网关进行身份验证,验证授权代码,并确保接收的重定向URI与网关注册时的URI相匹配。匹配成功后,授权服务器IAM响应返回访问令牌与可选的刷新令牌给网关。
为了前端会话保持,访问令牌由网关在响应时返回到前端,存储到前端存储空间,如Cookie、Local Storage、Session Storage等。
访问令牌失效后,网关根据自己的客户端凭证+刷新令牌一起发送授权服务器,获取新的访问令牌和刷新令牌,并再返回响应中将访问令牌写入到用户浏览器的存储中。
授权码模式中,用户的凭证(用户名、密码)是用户通过浏览器与授权服务交互,并不经过网关, 安全性最好。
模拟web端,使用移动端浏览器与WebView
使用URI scheme与Intent在应用间跳转
重定向过程中的回调URL参数,容易被恶意App占用URL Scheme或者监听localhost端口截取。
运行环境不可靠,移动App不具备安全保存客户端秘钥的能力,而使用授权码获取访问令牌时需要校验客户端秘钥。
(A) 移动App客户端创建并保存名为code_verifier的随机秘钥串,并将秘钥字符串加密转换的结果t(code_verifier)称为code_challenge,将转换后的code_challenge以及转换方法一并发送到授权服务中。
(B) 授权服务返回授权码并记录code_challenge和转换方法t_m。
(C) 移动App客户端收到授权码后,将授权码和code_verifier秘钥串发送到授权服务器,用以申请访问令牌。
(D) 授权服务器根据转换方法t_m 转换code_verifier 并与步骤A中收到的code_challenge比较,如果一致则返回访问令牌,否则拒绝非法请求。
rfc8252 - OAuth 2.0 for Native Apps
(https://tools.ietf.org/html/rfc825)
rfc7636 - Proof Key for Code Exchange by OAuth Public Clients
(https://tools.ietf.org/html/rfc7636)
(A)用户提供给特权App用户名和密码。
(B)特权App将用户凭据提交给授权服务器IAM,申请访问令牌
(C)授权服务器IAM 验证用户的凭证,如果有效,颁发访问令牌给特权App。特权App对授权服务器颁发的访问令牌、刷新令牌进行存储和更新。
虽然是特权App,但App中不要持久化保存用户密码,仅登录时使用
App负责保存Access Token 、Refresh Token
身份认证类API:即登录认证相关的API。为了避免用户、客户端凭证泄漏第三方(除IAM、访问者之外为第三方),身份认证类API或UI建议由IAM系统直接开放给访问者调用进行身份认证。
应用功能类API:功能实现来自服务提供者,通过网关开放给访问者。网关是访问应用API的入口。
方案一:网关委托授权服务验证,每次收到请求后,网关均将访问令牌发送到IAM认证服务进行认证,认证通过后才允许继续访问。
客户端成功认证后,使用UUID类型的访问令牌调用网关上的服务
由于UUID类型令牌不包含客户端的信息,网关需要委托IAM认证服务校验令牌
令牌检查合法后,将请求路由到服务提供者
应用中也无法解析令牌,需要根据UUID令牌到IAM中获取用户信息
方案二(推荐):网关直接验证,要求网关能识别IAM颁发的令牌,这种模式推荐用 JWT令牌,网关需要具备解析校验JWT加密的访问令牌的能力。
客户端成功认证后,使用JWT令牌调用网关上的服务
网关自己直接解密JWT令牌进行校验
令牌检查合法后,将请求路由到服务提供者
应用受到请求后,如果需要更多权限信息,如果可以根据Token去权限管理服务获取权限信息(非必须步骤,需要时添加)。
JWT令牌是防篡改的,但并不加密,如需要存储到浏览器存储中,建议采用JWT+JWE方式进行令牌加密。令牌中存放必要少量数据即可,避免滥用。多数服务器通常会对Http header、cookie长度做限制。
方案一,内部令牌:系统内的应用在发布接口到网关时,提供一个系统内部共享的令牌给网关和系统内所有应用,接收到请求时检查请求头中是否包含系统内信任的令牌, 如果包含可信任令牌,那么就允许访问,否则就拒绝
方案二,系统内保密令牌+网关证书单独认证:系统内用保密令牌交互就是方案一,只是内部令牌不共享给网关,网关用公私钥证书签名方式与域内系统建立信任,由网关生成公私钥证书,颁发公钥给各个系统,网关调用服务提供者时,请求头中带上用私钥签名的令牌,应用收到请求以后用网关发布的公钥验证其令牌。
客户端1获取了API Key 但其没有合法的访问令牌,如果不允许匿名访问,则网关会拒绝客户端1访问,返回错误码401表示客户端未通过认证;
客户端2拥有了合法的访问令牌,但其API Key不合法,网关在客户端2认证检查通过后,检查API Key,发现其权限不足,则返回错误码403表示客户端的权限不足;
客户端3拥有合法的客户端访问令牌和API Key访问网关上的服务,网关认证、鉴权通过之后,将请求路由到实际的服务提供端,最终发回正常响应数据。
为什么用了https就能保证通信安全呢?https是http+ssl,采用密码学手段对通信报文做了加密,使得报文无法被篡改,做到了安全传输,从而保障了通信安全。关于https原理和负载均衡器证书配置相关资料网络上有很多,请大家即用即查。
敏感配置加密:上述各种服务安全场景和方案聊了那么多,大家发现保存好令牌、密钥、密码是一切安全的前提。这些东西千万不能外泄。要保证密码不泄露的办法就是做好敏感数据保密,技术手段上则要求存储密码、凭证的地方(配置文件和数据库表)需要加密存储。如:配置文件中的数据库口令、数据表中存放的密码数据等
代码质量管理:建议在开发期对于编码规范进行制定,还可以通过工具进行辅助检查和控制,如开源的代码质量管理工具Sonar,可以支持多种程序语言,方便的与编译构建工具集成如Maven,在代码进入正式提交对应分支前就将一些安全问题在前期预防,如SQL注入等。
运行时安全扫描:测试阶段,可以通过安全扫描软件,如AppScan 等工具对业务系统的前后端功能进行扫描,检查系统漏洞并即时修复。尽量减小在上线运行后出现安全事故的风险。
运维管理安全方面,根据安全需求,要有安全相关的管理规范和工具支撑,对系统管理、权限分配和关键数据进行严格管控,并做好操作审计日志记录。
比如很多安全级别高的行业或企业中如军工类,对于业务系统的修改、权限管理审计做了严格的流程规范和功能支撑。如典型的三员管理,采用三权分立、互相制约的思路,包含系统管理员、安全管理员、安全审计员三个角色,互相能看到对方的信息,将业务过程分成不同的段,每段由对应人员负责,不让任何人掌控全局。
审计工作是非常重要的一环,没有任何系统和流程是绝对安全的。关键的操作、数据变化等审计日志需要完整记录。一旦发生问题,可以通过审计日志排查分析追踪。常见内容举例如下:
对于敏感数据项(如:密码)的访问
客户端注册、用户认证授权过程
权限的授予和废除
关键数据的变更、删除
审计功能的启动和关闭
其他关键API、命令的访问
以上这些审计方面的工作中,如果是基于API相关的审计信息记录,如边界交互报文数据,建议基于统一的技术框架进行记录管理。一些内部实现方法,则可以采用接口、方法上加注解,AOP拦截后记录的方案。其他情况可根据实际需求设计审计数据存储的方案。
参考引用
rfc6749-The OAuth 2.0 Authorization Framework
rfc8252-OAuth 2.0 for Native Apps
rfc7636-Proof Key for Code Exchange by OAuth Public Clien
PKCE授权码模式
如何在微服务架构中实现安全性
如何在移动端开发中正确地使用OAuth协议
推荐阅读
微服务来了,配置怎么办?
微服务的4个设计原则和19个解决方案
从微服务架构实施看企业数字化转型
关于作者:炎峰,现任普元金融研究院架构师。主要负责普元流程产品的核心架构设计与产品版本发展规划,先后参与了国家电网BPM、BAM平台、浦发银行新一代流程平台等大型平台项目建设与实施 。
关于EAWorld:微服务,DevOps,数据治理,移动架构原创技术分享。