Please enable Javascript to view the contents

如何快速接入统一的认证鉴权体系

 ·  ☕ 5 分钟

1. 异构系统带来的认证鉴权问题

企业系统,可以分为以下几种类型:

  • 购买的商业软件,比如 JumpServer
  • 开源的软件,比如 Kibana、Grafana
  • 自主研发的软件,比如应用管理平台

这里需要说明的是,认证和鉴权是两个功能:

  • 认证,证明你是你
  • 鉴权,你是管理员,而不是普通用户

针对上面的系统,在接入认证鉴权时,主要面临如下问题:

  • 自主定制成本高,而社区支持响应慢。定制开源组件需要投入大量人力,直接对其进行定制是不合时宜的,而将需求提交到社区等待解决方案,周期太长,难解燃眉之急
  • 自研系统一个一个对接认证鉴权成本很高。每一个自研系统都需要实现一套类似的逻辑,校验登录态,验证权限规则
  • 老的系统接入困难。有些老的服务相关人员离职,几乎没人维护但又有人在使用,改不动

对于商业购买的软件,在采购时就可对接入成本、安全性等进行评估,常常能够满足认证鉴权的需求。

而在大型企业中,不同的部门总是习惯性建设一套自己熟悉的认证鉴权系统,导致部门与部门之间的系统割裂,形成一个一个的烟囱壁垒,信息无法在内部自由流动。这给员工带来极大不便、大大降低工作效率,削弱企业在市场上的竞争力。

统一的认证鉴权体系是有必要的。公共的功能,通过服务化的形式提供给大家使用,不仅可以避免重复开发,还可以享受更优质的职能化服务。

2. 服务的域名策略

在进行登录态验证时,通常会需要获取 HTTP 请求的 Cookie。而 Cookie 的作用范围是和域名直接相关的。因此在聊统一认证鉴权之前,先了解一下服务的域名策略。

2.1 多域名多服务

为了服务之间彻底隔离,减小每次变更的影响范围,会采用多域名策略。示例如下:

harbor.oa.com
c.domain.com
www.chenshaowen.com

一个服务一个域名,减小了故障的爆炸半径,但也在管理上增加了很大成本,比如证书、DNS 配置等。如果没有统一的管理平面,这些复杂度的增加必然会增加人为失误、犯错的概率。控制复杂度是每个优秀的工程师必须掌握的技能。

统一的域名有利于树立良好的品牌形象。混乱的域名使用,会导致用户品牌识别度降低,误将李鬼当李逵,让黑产有机可乘。同时,多域名也不利于 SEO,分散服务在搜索引擎上的打分,降低排名。

因此,域名不要太多,在启用新域名之前,多思考能不能不用,采用尽可能少的原则使用。

在多域名策略下,我们只能以第三方登录的形态接入统一登录系统。每个系统申请一套接入凭证,然后各自进行对接。

2.2 单一域名多 Location

采用同一个域名,不同 Location 对应不同服务,是我推荐的一种做法。

domain.com/grafana/
domain.com/oa/
domain.com/c/
domain.com/c-test/

用户好记,研发也不用再苦恼于配置 Hosts,采用多域名时,每个服务配置一个 Hosts,甚是麻烦。

入口统一易于维护。多入口、多管理平面都是架构、运维能力弱的表现。谁都不会拒绝简单,直观、简洁、所见即所得是我们在设计系统时不断追求的目标。

由于采用单域名,这些系统之间的 Cookie 是共享的。因此只需要在该域名下写下登陆态 Cookie,用户使用其他系统时,也将处于登录状态。其他系统无需完成登录逻辑,只需要后台校验登陆态,再进行鉴权即可。

3. 通过七层 forward-auth 接入认证鉴权

如上图,无论是对于商业、自研、开源的软件,我们都可以通过七层网关统一认证鉴权。

下面是访问流程:

  1. 四层网关卸载证书。首先是 ELB 卸载 HTTPS 证书,统一接管用户的域名流量。当然,如果想限制访问来源,你还可以进行 IP 白名单限制。
  2. 七层网关路由。七层网关会对每一个 http 进行鉴权,获取用于认证的字段,这些字段可以是 Header 中的 JWT Token,也可以是整个 Cookie。对于没有通过 forward-auth 认证检测的请求,将会直接被拒绝。
  3. 进入业务系统。此时的用户已经完成了认证,但是缺少鉴权。如果是商业或者开源软件,可以通过 LDAP、Basic 二次认证之后,再获取角色权限。如果是自研的系统,可以在中间件中写鉴权逻辑,拿到用户 ID,请求统一的鉴权中心进行鉴权。

值得高兴的是,有些网关已经提供了这样的功能,比如 Apisix 的 forward-auth 插件,Traefik 的 forward-auth 中间件等,我们直接使用即可。下面是 forward-auth 需要实现的功能:

当有流量经过网关时,forward-auth 需要向指定的鉴权接口,发送一个请求,如果请求返回的是 200,那么放行流量;如果请求返回的是非 200,那么将进行重定向,将流量引导至认证页面。下面是在 Apisix 中给 forward-auth 的一段配置,以供大家参考:

Apisix 中 forward-auth 插件是 lua 编写,可以根据需要进行修改。比如,需要增加鉴权逻辑,只需要将 UID 和资源定位符 URI 传给统一的鉴权中心即可。

4. 通过 sidecar 接入认证鉴权

上面这种方式,我们是将认证放在了接入层,对业务系统没有任何改造。但是这种方式存在一个风险,如果绕过网关,就可以绕过认证。

在网关上实现的 forward-auth 认证的是南北向流量,即用户直接访问业务系统的流量。但这却无法控制东西向流量,其他服务依然可以对受控服务进行访问。另一种方式是,采用 Sidecar 进行认证鉴权,如下图:

我们需要开发一个 Sidecar,下沉网关层的 forward-auth,代理全部访问流量,进行统一认证鉴权之后再转发至受控业务。

这样就需要在每个受控系统上,部署一个 Sidecar。此时,用户请求的流量应该转发给 Sidecar 而不是业务本身。

5. 总结

本文主要思考的是在异构的系统下,如何快速接入统一的认证鉴权体系。

认证是证明你是你,而鉴权是证明你有权限这样做。在已有一套统一的认证鉴权系统的前提下,这里提供了两种快速接入的思路:

第一种是,采用网关层的 forward-auth,对业务无任何入侵,在接入层完成认证鉴权。通过后端 Middleware 二次验证,能够提供进一步的安全验证。

第二种是,采用 Sidecar 拦截受控业务的流量,进行认证鉴权之后,再转发流量。这种方式具有一定的开发量,但 Sidecar 可以复用,对业务代码没有入侵。其实,很多 Middleware 实现的功能都可以使用 Sidecar 实现,将开发成本转移到运维部署层面,当基础设施是 Kubernetes 时,我们又可以借助于 kube-apiserver 的准入控制 Webhook 实现自动注入,达到一次开发永久零成本使用的效果。

6. 参考


微信公众号
作者
微信公众号