Spring Security OAuth专题学习-背景

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/icarusliu/article/details/87911093

在公司项目中有使用到Spring Security OAuth2来对Spring Cloud集群的授权进行控制,为加深对这一技术的理解,自己花时间对OAuth的几个授权类型进行了学习,并记录如下。

本文主要介绍一些oauth2相关的背景知识及常见概念。后续将针对每一种授权模式进行实战演练。

1. 产生背景

在传统前后端不分离的WEB应用中,一般通过Session的方式来保存用户登录状态;每一个请求报文中都包含有Session相关信息,服务器端根据Session信息来判断用户登录是否过期是否需要重新登录。

然而前后端不分离的应用因为存在诸多如消耗资源大、可扩展性不强等问题,已经逐渐被企业所抛弃。前后端分离逐渐从盛行到成为主流。近年来,随着移动互联网技术的飞速发展,Web应用的客户端从传统的电脑网页到手机、平板及大屏设备、可穿戴设备等方向不断扩展,一个Web应用需要处理外部越来越多的不同种类的客户端请求;而在企业级应用内部,应用系统之间的调用越来越频繁,甚至多数系统也无法避免的需要与企业外部的系统进行交互。在这种情况下,资源权限控制成为现代企业必须要面对的问题。

先来看看在以下场景下,最开始的时候是如何处理权限同步的:

场景一:用户在A、B两个系统中均有账户,现在想要A去访问B中的用户数据;

场景二:用户需要通过两个或多个APP P1、P2访问到系统C中的数据;

对于这两种场景,最原始的作法都是在A系统中存储用户在B系统中的登录用户名及密码(场景一)、或者是在应用P1/P2中均存储系统C中的用户名及密码(场景二)。

从某种视角看这两种场景是类似的,有一个或者多个第三方的系统需要去访问用户存储在资源服务器中的用户资源;在这种场景下采用以上作法有以下弊端:

  • 增加了系统复杂度:一个系统可能需要存储一个甚至多个系统中的用户登录信息,同时需要调用这些系统API进行权限校验;
  • 用户名及密码信息存储在多个系统中,加大了用户信息泄露的机率;
  • 第三方的系统能够通过用户名与密码获取用户所有信息,而无法针对第三方系统进行定制化的授权;
  • 用户无法在收回某一个系统授权的情况下同时让其它系统能够正常访问;(如果他修改了密码,那么所有系统都将无法访问);
  • 用户修改密码会影响所有系统的访问,无法自动做到同步,除非用户去每一个系统中均修改密码。

OAuth就是在这种情况下应运而生的。

OAuth到目前为止已经有了两个版本。这两个版本之间的差异比较大,本文主要研究OAuth2在现代应用系统开发中的应用,如对OAuth1.0的内容感兴趣,可以参考以下网址:https://oauth.net/

默认情况下本文所讲的OAuth都代表的是OAuth2.0 。

2. OAuth2是什么

简单来说OAuth2是一种基于Token来进行访问资源权限控制的机制。

我们先来看下微信或者支付宝第三方授权登录的例子。假设现在有一个应用想要使用你的微信账号登录,它会包含有以下几个步骤:

  • 应用提供微信登录的按钮或者二维码;
  • 用户点击按钮或者使用微信扫描二维码;
  • 手机跳转到微信授权界面,提醒用户第三方应用请求访问应用哪些资源,是否同意或拒绝;
  • 用户同意授权,微信返回一串编码给第三方应用,第三方应用后续使用这个编码串调用微信相关接口来获取用户资源;

这就是一个很典型的OAuth2的应用场景,当前这边所列举的步骤基本都是用户能够感知的步骤,实际的实现过程远比这个要复杂。

结合这个场景,我们来理解下OAuth2是什么。

OAuth2是一种基于Token(即前文场景中用户授权成功后微信返回给第三方应用的那串编码)访问资源的权限控制方式;授权方提供集中的授权服务,客户端经过首次授权后,往后的每次访问都使用Token来访问相关资源。

Token

一般Token包含有两个: accessToken与refreshToken,前者用于资源访问;后者用于当accessToken失效后获取新的accessToken。

accessToken是有生效时间的,超过时间后如果还使用这个Token去访问资源,资源服务器将会进行超时提示;此时需要重新登录;

设想一下,即使我们一直在进行操作,accessToken仍旧会在一段时间后超时;因此每隔一段时间就要重新登录一次,很明显对于用户体验有非常大的影响。而通过引入RefreshToken即可改善这个问题。refreshToken同样也存在一个超时时间,不过它的超时时间比accessToken要长一些;当客户端发现accessToken超时后,即通过refreshToken获取新的accessToken和refreshToken;这个过程并不需要用户重新进行登录验证;因此可以大大的提升用户体验。

但如果RefreshToken也已经超时,那么此时就需要用户重新进行授权或者登录了。

3 关联方

OAuth2的关联方有以下四个:

  • 授权服务:用于进行用户登录、权限验证、客户端管理等的服务;
  • 资源服务:用于提供接口、图片等资源的应用服务;
  • 用户:资源服务中的资源所属用户,一般对应于在资源服务及授权服务中的一个账号;
  • 客户端:想要访问资源服务中的接口或者其它数据的第三方服务;

在小型系统中资源服务与授权服务可以在同一个应用中;也可以将授权服务拆分到独立的应用中,同时资源服务按业务或者其它维度拆分成多个资源服务应用进行部署,不同的资源服务应用使用同一个授权服务。

针对微信的示例,我们都是微信的一个个用户;在微信的后台服务中对应有一个个账号;微信后台服务存储有很多我们的信息与数据;我们登录验证等都是在微信的专用授权服务中进行,而信息与数据则存储在它的资源服务中;那些想要获取我们的用户信息与数据的第三方应用(如APP或者小程序),就是OAuth2中的客户端。

在客户端调用授权服务相关接口获取Token之前,客户端需要在授权服务中进行注册,获取到自己的客户端ID、密码、可访问的资源编号等信息后,才可进行下一步动作。

4 授权模式

根据获取Token的方式不同,授权模式可以分成以下几种方式:

  • 客户端模式: 使用客户端相关信息如客户端名称、密码可登录授权服务器并获取Token。但其所获取的Token为客户端权限,能够访问资源服务器中的那些公开的或者需要登录用户或者是直接指定客户端权限的资源;对于需要用户权限的那些资源是无法访问的。因此这种模式使用场景比较有限。
  • 密码模式:客户端保存用户密码(或者用户直接在客户端输入密码,如APP的登录等);然后客户端直接使用用户密码去授权服务器获取Token,再使用获取的Token去访问资源服务器的相关资源。这种模式一般使用在公司内部APP与内部资源服务器之间的授权验证。因为客户端是能够直接获取到用户密码的,因此对于外部应用如果采用这种模式,风险很大。
  • 授权码模式:最复杂安全性最好的方式。客户端将用户导向授权服务器,授权服务器授权后返回一个授权码给客户端,客户端使用这个授权码调用授权服务器接口获取Token,然后后续的每次请求都使用这个Token。
  • 简化模式:简化模式是在授权码模式基础上进行简化,在第一种授权服务器验证完用户身份后,直接返回token给客户端(通过访问客户端配置的URL访问客户端指定页面,将Token传输给客户端)。
  • 刷新码模式:即使用refreshToken获取Token的方式。

对于授权服务器而言,它可以所有模式都支持,然后限制某些客户端只能使用某些模式。因此这些模式实际上是可以共存的。

5 JWT

JWT是JSON Web Token的简称。它是一种Token格式。与普通Token不一样的地方在于,它可以在Token中存储许多其它的信息,如用户信息、授权相关信息等。资源服务器在接收到JWT类型的Token时,通过公钥或者其它方式去验证Token的有效性;如果有效,那么再解析出登录用户所拥有的权限是否能够访问指定资源。不可以则返回权限不够等异常,权限足够时则访问对应的资源或接口。

猜你喜欢

转载自blog.csdn.net/icarusliu/article/details/87911093