微服务架构如何设计API代理网关和OAuth2授权认证框架

1,授权认证与微服务架构

1.1,由不同团队合作引发的授权认证问题

去年的时候,公司开发一款新产品,但人手不够,将B/S系统的Web开发外包,外包团队使用Vue.js框架,调用我们的WebAPI,但是这些WebAPI并不在一台服务器上,甚至可能是第三方提供的WebAPI。同时处于系统安全的架构设计,后端WebAPI是不能直接暴露在外面的;另一方面,我们这个新产品还有一个C/S系统,C端登录的时候,要求统一到B/S端登录,可以从C端无障碍的访问任意B/S端的页面,也可以调用B/S系统的一些API,所以又增加了一个API网关代理。

整个系统的架构示意图如下:

微服务架构如何设计API代理网关和OAuth2授权认证框架

 

注:上图还有一个iMSF,这是一个实时消息服务框架,这里用来做文件服务,参见《消息服务框架使用案例之--大文件上传(断点续传)功能》。在Web端会读取这些上传的文件。

1.2,微服务--分布式“最彻底”的分

1.2.1,为什么需要分布式

大部分情况下,如果你的系统不是很复杂,API和授权认证服务,文件服务都可以放到一台服务器:Web Port 服务器上,但要把它们分开部署到不同的站点,或者不同的服务器,主要是出于以下考虑:

1,职责单一:每一个服务都只做一类工作,比如某某业务WebAPI,授权服务,用户身份认证服务,文件服务等;职责单一使得开发、部署和维护变得容易,比如很容易知道当前是授权服务的问题,而不是业务API问题。

2,系统安全:采用内外网隔离的方案,一些功能需要直接暴露在公网,这需要付出额外的成本,比如带宽租用和安全设施;另外一些功能部署在内网,这样能够提供更大的安全保证。

3,易于维护:每一个服务职责都比较单一,所以每一个服务都足够小,那么开发维护就更容易,比如要更新一个功能,只需要更新一个服务而不用所有服务器都暂停;另一方面也更加容易监控服务器的负载,如果发现某一个服务器负载太大可以增加服务器来分散负载。

4,第三方接入:现在系统越来越复杂,内部的系统很可能需要跟第三方的系统对接,一起协同工作;或者整个系统一部分是 .NET开发的,一部分又是Java平台开发的,两个平台部署的环境有很大差异,没法部署在一起;或者虽然同是ASP.NET MVC,但是一个是MVC3,一个是MVC5,所以需要分别独立部署。

以上就是各个服务需要分开部署的原因,而这样做的结果就是我们常说的分布式计算了,这是自然需求的结果,不是为了分而拆分。

1.2.2,依赖于中间层而不直接依赖于服务

客户端直接访问后端服务,对后端的服务会形成比较强的依赖。有架构经验的朋友都知道,解决依赖的常见手段就是添加一个中间层,客户端依赖于这个中间层而不是直接依赖于服务层。这样做有几个很大的好处:

  • 当服务负载过大的时候可以在中间层做负载均衡;
  • 或者后端某个服务出现问题可以切换主备服务;
  • 或者替换后端某个服务的版本做灰度发布。

另一方面,当后端服务部署为多个独立的进程/服务器后,客户端直接访问这些服务,将是一个更加较复杂的问题,负载均衡,主备切换,灰度发布等运维功能更难操作,除此之外,还有下面两个比较重要的问题:

  • 客户端直接访问后端多个服务,将暴露过多的后端服务器地址,从而增加安全隐患;
  • 后端服务太多,需要在客户端维护这些服务访问关系,增加开发调试的复杂性;
  • B/S页面的AJax跨域问题,WebAPI地址跟主站地址不一样,要解决跨域问题比较复杂并且也会增加安全隐患。

所以,为了解决客户端对后端服务层的依赖,并且解决后端服务太多以后引起的问题,我们需要在客户端和后端服务层之间添加一个中间层,这个中间层就是我们的服务代理层,也就是我们后面说的服务网关代理(WebAPI Gateway Proxy),它作为我们所有Web访问的入口站点,这就是上图所示的 Web Port。有了网关代理,后台所有的WebAPI都可以通过这个统一的入口提供对外服务的功能,而对于后端不同服务地址的路由,由网关代理的路由功能来实现,所以这个代理功能很像Nginx这样的反向代理,只不过,这里仅仅代理WebAPI,而不是其它Web资源。

现在,网关已经成为很多分布式系统的标配,比如TX的这个架构:

微服务架构如何设计API代理网关和OAuth2授权认证框架

 

注:上图来源于网络,侵删!

另外,这个读写分离代理,如果使用SOD框架,可以在AdoHelper对象直接设置读写不同的连接字符串简单达到效果。

1.2.3,微服务架构

经过上面的设计,我们发现这个架构有几个特点:

  1. 每个服务足够小,职责单一;
  2. 每个服务运行在自己的进程或者独立的服务器中,独立发布部署和开发维护;
  3. 服务对外提供访问或者服务之间进行通信,都是使用轻量级的HTTP API;
  4. 每个服务有自己独立的存储,彼此之间进行数据交互都通过接口进行;
  5. 有一个API代理网关统一提供服务的对外访问。

这些特点是非常符合现在流行的微服务思想的,比如在《什么是微服务》这篇文章中,像下面说的这样:

微服务最早由Martin Fowler与James Lewis于2014年共同提出,微服务架构风格是一种使用一套小服务来开发单个应用的方式途径,每个服务运行在自己的进程中,
并使用轻量级机制通信,通常是HTTP API,这些服务基于业务能力构建,并能够通过自动化部署机制来独立部署,这些服务使用不同的编程语言实现,以及不同数据存储技术,
并保持最低限度的集中式管理。

所以我们这个架构是基本符合微服务思想的,它的诞生背景也是要解决其它传统单体软件项目现在遇到的问题一样的,是在比较复杂的实际需求环境下自然而然的一种需求,不过好在它没有过多的“技术债务”,所以设计实施起来比较容易。下面我们来详细看看这个架构是如何落地的。

2,“授权\认证\资源”独立服务的OAuth2.0架构

2.1,为什么需要OAuth2.0 ?

OAuth 2.0已经是一个“用户验证和授权”的工业级标准。OAuth(开放授权)是一个开放标准,1.0版本于2006年创立,它允许用户让第三方应用访问该用户在某一网站上存储的私密的资源(如照片,视频,联系人列表),而无需将用户名和密码提供给第三方应用。 OAuth 2.0关注客户端开发者的简易性,同时为Web应用,桌面应用和手机,和起居室设备提供专门的认证流程。2012年10月,OAuth 2.0协议正式发布为RFC 6749。以上内容详见OAuth 2.0官网。

现在百度开放平台,腾讯开放平台等大部分的开放平台都是使用的OAuth 2.0协议作为支撑,国内越来越多的企业都开始支持OAuth2.0协议。现在,我们的产品设计目标是要能够和第三方系统对接,那么在对接过程中的授权问题就是无法回避的问题。在我们原来的产品中,有用户授权验证的模块,但并没有拆分出独立的服务,用它与第三方系统对接会导致比较大的耦合性;另一方面,与第三方系统对接合作不一定每次都是以我们为主导,也有可能要用第三方的授权认证系统。这就出现了选择哪一方的授权认证方案的问题。之前我曾经经历过一个项目,因为其中的授权认证问题导致系统迟迟不能集成。所以,选择一个开放标准的授权认证方案,才是最佳的解决方案,而OAuth 2.0正是这样的方案。

2.2,OAuth的名词解释和规范

(1)Third-party application:第三方应用程序,本文中又称”客户端”(client),即上一节例子中的“Web Port”或者C/S客户端应用程序。
(2)HTTP service:HTTP服务提供商,即上一节例子中提供软件产品的我们公司或者第三方公司。
(3)Resource Owner:资源所有者,本文中又称“用户”(user)。
(4)User Agent:用户代理,本文中就是指浏览器或者C/S客户端应用程序。
(5)Authorization server:授权服务器,即服务提供商专门用来处理认证的服务器。
(6)Resource server:资源服务器,即服务提供商存放用户生成的资源的服务器,即上一节例子中的内部API服务器、第三方外部API服务器和文件服务器等。它与认证服务器,可以是同一台服务器,也可以是不同的服务器。

以上名词是OAuth规范内必须理解的一些名词,然后我们才能方便的讨论OAuth2.0是如何授权的。有关OAuth的思路、运行流程和详细的四种授权模式,请参考阮一峰老师的《理解OAuth 2.0》。

2.3,OAuth2.0的授权模式

为了表述方便,先简单说说这4种授权模式:

  1. 授权码模式(authorization code)--是功能最完整、流程最严密的授权模式。它的特点就是通过客户端的后台服务器,与"服务提供商"的认证服务器进行互动。
  2. 简化模式(implicit)--不通过第三方应用程序的服务器,直接在浏览器中向认证服务器申请令牌,跳过了"授权码"这个步骤,因此得名。所有步骤在浏览器中完成,令牌对访问者是可见的,且客户端不需要认证。
  3. 密码模式(resource owner password credentials)--用户向客户端提供自己的用户名和密码。客户端使用这些信息,向"服务商提供商"索要授权。在这种模式中,用户必须把自己的密码给客户端,但是客户端不得储存密码。
  4. 客户端模式(client credentials)--指客户端以自己的名义,而不是以用户的名义,向"服务提供商"进行认证。严格地说,客户端模式并不属于OAuth框架所要解决的问题。在这种模式中,用户直接向客户端注册,客户端以自己的名义要求"服务提供商"提供服务,其实不存在授权问题。

在我们的需求中,用户不仅仅通过B/S系统的浏览器进行操作,还会通过C/S程序的客户端进行操作,B/S,C/S系统主要都是我们提供和集成的,客户购买了我们这个产品要使用它就意味着客户信任我们的产品。授权码模式虽然是最完整的授权模式,但是授权码模式授权完成后需要浏览器的跳转,显然浏览器无法直接跳转到我们的C/S客户端,虽然从技术上可以模拟,但实现起来成本还是比较高;简化模式也有这个问题。所以我们最终决定采用OAuth2.0的密码模式。

2.4,OAuth2.0密码模式授权流程

简单来说,密码模式的步骤如下:

  1. 用户向客户端提供用户名和密码。
  2. 客户端将用户名和密码发给认证服务器,向后者请求令牌。
  3. 认证服务器确认无误后,向客户端提供访问令牌。

上面这个步骤只是说明了令牌的获取过程,也就是我们常说用户登陆成功的过程。当用户登陆成功之后,客户端得到了一个访问令牌,然后再使用这个令牌去访问资源服务器,具体说来还有如下后续过程:

  • 4,客户端携带此访问令牌,访问资源服务器;
  • 5,资源服务器去授权服务器验证客户端的访问令牌是否有效;
  • 6,如果访问令牌有效,授权服务器给资源服务器发送用户标识信息;
  • 7,资源服务器根据用户标识信息,处理业务请求,最后发送响应结果给客户端。

下面是流程图:

微服务架构如何设计API代理网关和OAuth2授权认证框架

 

注意:这个流程适用于资源服务器、授权服务器相分离的情况,否则,流程中的第5,6步不是必须的,甚至第4,7步都是显而易见的事情而不必说明。现在大部分有关OAuth2.0的介绍文章都没有4,5,6,7步骤的说明,可能为了表述方便,默认都是将授权服务器跟资源服务器合在一起部署的。

2.5,授权、认证与资源服务的分离

什么情况下授权服务器跟资源服务器必须分开呢?

如果一个系统有多个资源服务器并且这些资源服务器的框架版本不兼容,运行环境有差异,代码平台不同(比如一个是.NET,一个是Java),或者一个是内部系统,一个是外部的第三方系统,必须分开部署。在这些情况下,授权服务器跟任意一个资源服务器部署在一起都不利于另一些资源服务器的使用,导致系统集成成本增加。这个时候,授权服务器必须跟资源服务器分开部署,我们在具体实现OAuth2.0系统的时候,需要做更多的事情。

什么情况下授权服务器跟认证服务器必须分开呢?

授权(authorization)和认证(authentication)有相似之处,但也是两个不同的概念:

  • 授权(authorization):授权,批准;批准(或授权)的证书;
  • 认证(authentication):认证;身份验证;证明,鉴定;密押。

仅仅从这两个词的名词定义可能不太容易分辨,我们用实际的例子来说明他们的区别:

有一个管理系统,包括成熟的人员管理,角色管理,权限管理,系统登录的时候,用户输入的用户名和密码到系统的人员信息表中查询,通过后取得该用户的角色权限。

在这个场景中,用户登录系统实际上分为了3个步骤:

  1. 用户在登录界面,输入用户名和密码,提交登录请求;
  2. 【认证】系统校验用户输入的用户名和密码是否在人员信息表中;
  3. 【授权】给当前用户授予相应的角色权限。

现在,该管理系统需要和第三方系统对接,根据前面的分析,这种情况下最好将授权功能独立出来,采用OAuth这种开放授权方案,而认证问题,原有管理系统坚持用户信息是敏感信息,不能随意泄露给第三方,要求在原来管理系统完成认证。这样一来,授权和认证,只好分别作为两个服务,独立部署实现了。

本文的重点就是讲述如何在授权服务器和资源服务器相分离,甚至授权和认证服务器相分离的情况下,如何设计实现OAuth2.0的问题。

3,PWMIS OAuth2.0 方案

PWMIS OAuth2.0 方案就是一个符合上面要求的授权与认证相分离,授权与资源服务相分离的架构设计方案,该方案已经成功支撑了我们产品的应用。下面分别来说说该方案是如何设计和落地的。

3.1,使用Owin中间件搭建OAuth2.0认证授权服务器

这里主要总结下本人在这个产品中搭建OAuth2.0服务器工作的经验。至于为何需要OAuth2.0、为何是Owin、什么是Owin等问题,不再赘述。我假定读者是使用Asp.Net,并需要搭建OAuth2.0服务器,对于涉及的Asp.Net Identity(Claims Based Authentication)、Owin、OAuth2.0等知识点已有基本了解。若不了解,请先参考以下文章:

  • MVC5 - ASP.NET Identity登录原理 - Claims-based认证和OWIN
  • 下一代Asp.net开发规范OWIN(1)—— OWIN产生的背景以及简单介绍
  • OWIN OAuth 2.0 Authorization Server

我们的工作,可以从研究《OWIN OAuth 2.0 Authorization Server》这个DEMO开始,不过为了更好的结合本文的主题,实现授权与认证相分离的微服务架构,推荐大家直接从我的DEMO开始:https://github.com/bluedoctor/PWMIS.OAuth2.0

PS:大家觉得好,先点个赞支持下,谢谢!

克隆我这个DEMO到本地,下面开始我们OAuth2.0如何落地的正式讲解。

3.2,PWMIS.OAuth2.0解决方案介绍

首先看到解决方案视图,先逐个做下简单说明:

微服务架构如何设计API代理网关和OAuth2授权认证框架

 

3.2.1,运行解决方案

将解决方案的项目,除了PWMIS.OAuth2.Tools,全部设置为启动项目,启动之后,在 http://localhost:62424/ 站点,输入下面的地址:

http://localhost:62424/Home

然后就可以看到下面的界面:

微服务架构如何设计API代理网关和OAuth2授权认证框架

 

点击登录页面,为了方便演示,不真正验证用户名和密码,所以随意输入,提交后结果如下图:

微服务架构如何设计API代理网关和OAuth2授权认证框架

 

点击确定,进入了业务操作页面,如下图:

微服务架构如何设计API代理网关和OAuth2授权认证框架

 

如果能够看到这个页面,我们的OAuth2.0演示程序就成功了。

还可以运行解决方案里面的WinFo

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值