Spring Authorization Server

Spring Authorization Server 是一个框架,它提供了 OAuth 2.1 和 OpenID Connect 1.0 规范以及其他相关规范的实现。它建立在 Spring Security 之上,为构建 OpenID Connect 1.0 身份提供者和OAuth2授权服务器产品提供了一个安全、轻量级和可定制的基础。说白了,Spring Authorization Server 就是一个认证(授权)服务器。
官方文档

1. 发展

因为随着网络和设备的发展,原先的 OAuth 2.0 已经不能满足现今的需求了,OAuth 社区对 OAuth 2.0 中的几种授权模式进行了取舍和优化,并增加一些新的特性, 于是推出了 OAuth 2.1,而原先的 Spring Security OAuth 2.0 使用的是 OAuth 2.0 协议,为满足新的变化,Spring Security 团队重新写了一套叫 Spring Authorization Server 的认证授权框架来替换原先的 Spring Security OAuth 2.0。从官网中可以看到,原先的 Spring Security OAuth 2.0 已从 Spring Security 目录下被移除,接着是多出 Spring Authorization Server 作为单独项目。

2. OAuth2

2.1 OAuth2是什么
  • “Auth” 表示 “授权” Authorization
  • “O” 是 Open 的简称,表示 “开放”
  • 连在一起就表示 “开放授权”,OAuth2是一种开放授权协议。
2.2 OAuth2的角色

OAuth 2协议包含以下角色:

  1. 资源所有者(Resource Owner):即用户,资源的拥有人,想要通过客户应用访问资源服务器上的资源。
  2. 客户应用(Client):通常是一个Web或者无线应用,它需要访问用户的受保护资源。
  3. 资源服务器(Resource Server):存储受保护资源的服务器或定义了可以访问到资源的API,接收并验证客户端的访问令牌,以决定是否授权访问资源。
  4. 授权服务器(Authorization Server):负责验证资源所有者的身份并向客户端颁发访问令牌。
2.3 OAuth2的使用场景

1. 开放系统间授权

  • 社交登录
    在传统的身份验证中,用户需要提供用户名和密码,还有很多网站登录时,允许使用第三方网站的身份,这称为"第三方登录"。所谓第三方登录,实质就是 OAuth 授权。用户想要登录 A 网站,A 网站让用户提供第三方网站的数据,证明自己的身份。获取第三方网站的身份数据,就需要 OAuth 授权。最常用的就是用微信、QQ、微博等信息去登录一些其他网站,比如:用微信登录iconfont,用QQ登录千库网等。
  • 开放API
    对接过微信、支付宝等接口的同学应该都知道。一般都会先登录拿到token,然后带token去请求接口。这个过程就是OAuth2的使用,只不过OAuth2服务器由微信或者支付宝提供。
    2. 现代微服务安全
    像政府政务部门,多个部门若整合在一起,当登陆后可以获取不同信息
    微服务

    3. 企业内部多应用
    企业一般有ERP系统,还有生产业务系统等,当我们进行SSO单点登录后,可以访问不同系统。
2.4 OAuth2的四种授权模式
  • 授权码模式(authorization-code)
  • 简化模式(隐藏式)(implicit)
  • 密码模式(password)
  • 客户端模式(client credentials)

注意,不管哪一种授权方式,第三方应用申请令牌之前,都必须先到系统备案,说明自己的身份,然后会拿到两个身份识别码:客户端 ID(client ID)和客户端密钥(client secret)。这是为了防止令牌被滥用,没有备案过的第三方应用,是不会拿到令牌的。

2.4.1 授权码模式

授权码(authorization code),指的是第三方应用先申请一个授权码,然后再用该码获取令牌。
这种方式是最常用,最复杂,也是最安全的,它适用于那些有后端的 Web 应用,一般是2家不同企业对接。授权码通过前端传送,令牌则是储存在后端,而且所有与资源服务器的通信都在后端完成。这样的前后端分离,可以避免令牌泄漏。

授权码模式

// 第一步:A前端请求B授权码
https://b.com/oauth/authorize?
  response_type=code&
  client_id=CLIENT_ID&
  redirect_uri=CALLBACK_URL&
  scope=read
// 第二步:B返回授权码到A的前台地址
https://a.com/callback?code=AUTHORIZATION_CODE
// 第三步:A前端发送code到A后台,A后台去B请求令牌
https://b.com/oauth/token?
 client_id=CLIENT_ID&
 client_secret=CLIENT_SECRET&
 grant_type=authorization_code&
 code=AUTHORIZATION_CODE&
 redirect_uri=CALLBACK_URL
// 第四步:B返回令牌数据
{    
  "access_token":"ACCESS_TOKEN",
  "token_type":"bearer",
  "expires_in":2592000,
  "refresh_token":"REFRESH_TOKEN",
  "scope":"read"
}
2.4.2 简化模式

有些 Web 应用是纯前端应用,没有后端。这时就不能用上面的方式了,必须将令牌储存在前端。RFC 6749 就规定了第二种方式,允许直接向前端颁发令牌。这种方式没有授权码这个中间步骤,所以称为(授权码)"隐藏式"(implicit)。


隐藏式

这种方式把令牌直接传给前端,是很不安全的。因此,只能用于一些安全要求不高的场景,并且令牌的有效期必须非常短,通常就是会话期间(session)有效,浏览器关掉,令牌就失效了。

// 第一步:A 提供一个链接,要求用户跳转到 B 网站,授权用户数据给 A 网站使用
https://b.com/oauth/authorize?
  response_type=token&
  client_id=CLIENT_ID&
  redirect_uri=CALLBACK_URL&
  scope=read
// 第二步:用户跳转到 B 网站,登录后同意给予 A 网站授权。这时,B 网站就会跳回redirect_uri参数指定的跳转网址,并且把令牌作为 URL 参数,传给 A 网站。
https://a.com/callback#token=ACCESS_TOKEN
// 注意,令牌的位置是 URL 锚点(fragment),而不是查询字符串(querystring),这是因为 OAuth 2.0 允许跳转网址是 HTTP 协议,因此存在"中间人攻击"的风险,而浏览器跳转时,锚点不会发到服务器,就减少了泄漏令牌的风险。
2.4.3 密码模式

密码模式一般是企业内部应用使用的,比如前台登陆,应该使用这个最多了,我们在开发自己的系统时,也是用的这个。
区别于 简化模式,密码模式 需要带 账号和密码,还有需要将client ID和client security放入请求头:
第一步:用账号密码直接请求token

// header
Authorization: Basic Base64.encode(client ID:client security)
// 请求
https://b.com/oauth/token?
  grant_type=password&
  username=USERNAME&
  password=PASSWORD&
  scope=read

第二步: 拿到token

{    
  "access_token":"ACCESS_TOKEN",
  "token_type":"bearer",
  "expires_in":7200,
  "refresh_token":"REFRESH_TOKEN"
}
2.4.4 客户端模式

凭证式(client credentials):也叫客户端模式,适用于没有前端的命令行应用,即在命令行下请求令牌。
这种方式给出的令牌,是针对第三方应用的,而不是针对用户的,即有可能多个用户共享同一个令牌。由于不涉及用户,一般是服务器对服务器。

另外,当有refresh_token时,我们可以用refresh_token定时更新token,防止过期。

3. Spring Authorization Server模式

上面说了,Spring Authorization Server 提供了 OAuth 2.1 和 OpenID Connect 1.0 规范以及其他相关规范的实现。与2.0相比,有一些不同:

  • OAuth 2.1去掉了OAuth2.0中的密码模式、简化模式,
  • OAuth 2.1增加了设备授权码模式
  • OAuth 2.1对授权码模式增加了PKCE扩展
3.1 客户端模式

OAuth2.0 的客户端模式在 OAuth 2.1 中被保留了下来,客户端模式更形象的理解,应该叫“合作方模式”更为贴切,因为整个数据交互过程中,至始至终都只有服务器提供方和服务调用方,全程都未有用户的参与。客户端模式交互过程,见上文 OAuth2.0 客户端模式的讲解。

3.2 授权码模式

授权码模式交互过程,见上文 OAuth2.0 授权码模式的讲解。这里要说的是授权码模式如何拓展 PKCE。
在授权码模式的交互工程中,有一个环节比较薄弱,这个环节就是认证服务器返回授权码的过程中,如果恶意程序截取到授权码,那么恶意程序就可以进而通过授权码窃取令牌了。为了减轻这种攻击,官方增加PKCE扩展,先来看一下官方的交互图。


image.png
    1. 客户端通过“/oauth2/authorize”地址向认证服务器发起获取授权码请求的时候增加两个参数,即code_challengecode_challenge_method,其中,code_challenge_method 是加密方法(例如:S256 或 plain),code_challenge是使用code_challenge_method加密方法加密后的值。
    1. 认证服务器给客户端返回授权码,同时记录下code_challengecode_challenge_method的值。
    1. 客户端使用 code 向认证服务器获取Access Token的时候,带上code_verifier 参数,其值为步骤1加密前的初始值。
    1. 认证服务器收到步骤3的请求时,将code_verifier的值使用 code_challenge_method的方法进行加密,然后将加密后的值与步骤A中的 code_challenge进行比较,看看是否一致。
      上面交互过程中,恶意程序如果在2处截获授权码后,使用授权码向认证服务器换取 Access Token,但由于恶意程序没有code_verifier的值,因此在认证服务器无法校验通过,从而获取Access Token失败。
3.3 设备授权码模式

设备授权码模式,是一种为解决不便在当前设备上进行文本输入而提供的一种认证授权模式,例如:智能电视、媒体控制台、数字相框、打印机等。大家也可以脑补一下一些扫码登录的情形。使用设备授权码模式,有以下要求。
(1) 该设备已连接到互联网。
(2) 设备能够支持发出 HTTPS 请求。
(3) 设备能够显示或以其他通信方式将 URI 和 Code 发给用户。
(4) 用户有辅助设备(如个人电脑或智能手机),他们可以从中处理请求。
设备授权码登录官网交互图如下。


image.png
    1. 客户端带上包含客户端信息的参数向认证服务器(地址:/oauth2/device_authorization)发起授权访问。
    1. 认证服务器给客户端返回设备码、用户码及需要用户验证用户码的 URI。
    1. 客户端指示用户需要在另一设备进行访问授权的URI和用户码。
    1. 用户根据URI打开页面,输入用户码和确认授权,向认证服务器发起认证请求。
    1. 客户端在完成步骤3 之后就开始带上客户端信息和设备码向认证服务器轮询获取令牌信息。
    1. 认证服务器收到客户端使用设备码获取令牌信息的请求后,检查用户是否已提交授权确认,如果用户已提交授权确认,则返回令牌信息。
3.4 拓展授权模式

OAuth2.1 也提供拓展授权模式的操作实现。虽然 OAuth2.1 移除了密码模式(password),但是通过拓展授权模式可以实现密码模式。在实际应用中,客户端、认证服务器、资源服务器往往都是同一家公司的产品,那么这个时候,使用账号、密码进行登录的情形也比较常见,此时就需要通过拓展授权模式来实现账号、密码登录了。可以查看自定义授权模式官网文档地址

4. OpenID Connect 1.0

OpenID Connect 1.0 是 OAuth 2.0 协议之上的一个简单的身份层。其实就是客户端向认证服务器请求认证授权的时候,多返回一个 id_token,该 id_token 是一串使用 jwt 加密过的字符串。
ID Token(身份令牌)和 Access Token(访问令牌)是两个不同的令牌,它们在身份验证和访问控制的流程中发挥不同的作用。我现在只使用Access Token(访问令牌)

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,591评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,448评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,823评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,204评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,228评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,190评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,078评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,923评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,334评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,550评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,727评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,428评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,022评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,672评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,826评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,734评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,619评论 2 354

推荐阅读更多精彩内容