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