首页 > 其他分享 >Spring Security系列教程29--OAuth2.0协议详解

Spring Security系列教程29--OAuth2.0协议详解

时间:2022-12-24 12:34:16浏览次数:75  
标签:QQ 令牌 -- Spring 29 服务器 授权 OAuth2.0 客户端


前言

截止到现在,一一哥 已经带各位把Spring Security中的主要功能学完了,并且剖析了这些内容的底层实现原理,希望你可以有所收获。

但是在安全认证领域,还有另一种很重要的授权机制---OAuth2.0开放授权。而且OAuth2.0开放授权与Spring Security经常配合使用,这两者之间可以说是“焦不离孟,孟不离焦”的搭配关系,所以为了进一步掌握Spring Security,在这里 壹哥 给大家再介绍另一个OAuth2.0开放授权协议。

OAuth2.0开放授权并不是Spring Security框架里的一部分,只是两者经常配合使用而已,所以我得先给大家普及一下OAuth2.0的内容,毕竟OAuth2.0的内容还是蛮难理解的。

一. OAuth2.0简介

1. OAuth2.0概述

咱们先来看看在RFC6749号文件中对OAuth2.0的定义,如下图所示:

Spring Security系列教程29--OAuth2.0协议详解_服务器

简单来说,OAuth2.0 是一种授权机制,其内部引入了一个授权层,可以分离两种不同的角色:客户端和资源所有者。资源所有者同意客户端(第三方应用程序)的请求以后,资源服务器就可以向客户端颁发短期的进入令牌(token),用来代替密码,客户端通过这个令牌,去请求有限的资源数据来使用。所以OAuth2.0 的核心就是向第三方应用颁发令牌。

2. OAuth2.0发展历程

OAuth(Open Authorization)--开放授权,这是一种关于开放授权的协议标准。所谓的OAuth2.0,表示这是OAuth协议第2版,但并不兼容之前的OAuth1.0协议,即现在已经完全废止了OAuth1.0协议。

那么为什么会废止OAuth1.0协议呢?我们先来简单说一下OAuth协议的发展历程。

2007年12月的时候,OAuth协议已经诞生了,并与2010年4月份,被IETF(国际互联网工程任务组)认可并作为认证授权的标准发布。但是这个OAuth1.0协议有些致命缺陷,就是它的签名逻辑特别复杂,开发时对程序员来说极度恶心。而且OAuth1.0的授权流程是很单一,存在较大的漏洞,容易被黑客gongji。所以在2012年10月的时候,IETF又更新发布了OAuth2.0协议,在这个版本中,放弃了之前复杂的数字签名和加密方案,使用HTTPS来作为安全保障手段,这降低了程序员的开发难度。但是OAuth2.0协议与OAuth1.0协议互不兼容,所以现在我们进行开发时,都是采用OAuth2.0协议,而不再采用OAuth1.0协议。

3. OAuth2.0功能

通过上一小节,我们了解到OAuth是一种关于开放授权的协议,该协议其实是一个 服务提供商 授权 第三方应用 获取 资源所有者 部分访问权限 的授权机制。通俗的说,就是OAuth协议允许用户在不提供密码给第三方应用的情况下,使得第三方应用有权获取用户数据等基本信息。在整个授权过程中,第三方应用都不必获取用户的密码,就可以取得用户部分资源的使用权限,所以OAuth是一种安全开发的协议。

比如我们在CSDN上进行登录时,可以利用CSDN这个平台自身注册的账号,也可以使用第三方账号(QQ、微信、微博等)来进行登录,如下图:

Spring Security系列教程29--OAuth2.0协议详解_客户端_02

Spring Security系列教程29--OAuth2.0协议详解_访问令牌_03编辑

比如我们选择利用QQ账号登录CSDN,如下图:

Spring Security系列教程29--OAuth2.0协议详解_服务器_04

这时候我们可以打开QQ扫码,或者点击自己的QQ头像,就可以实现利用QQ帐号登录到CSDN这个网站上。在这个过程中,我们其实不必担心自己的QQ密码会泄露给CSDN,因为CSDN是拿不到我们的QQ密码的。

在这个登录过程中,CSDN相对于QQ来说是第三方应用,QQ就是服务提供商。在QQ内部,会有一个认证服务器作为专门的授权中心,QQ用户的用户名头像等信息都属于资源,这些资源可能会存放在一台专门的资源服务器上,也可能会直接存放在QQ的认证服务器上。当CSDN经过了QQ的认证之后,就可以获取到QQ上的用户昵称、头像、性别等信息,从而实现利用QQ的用户,登录到CSDN的网站上,免除用户重复的注册过程。

4. OAuth2.0使用场景

根据上一小节,我们可以总结一下OAuth2.0的使用场景,大致如下:

  • 第三方应用登录:比如利用QQ,微博,微信授权登录到其他网站或App。
  • 分布式或微服务项目中授权:在Java分布式或微服务开发时,后端业务拆分成若干服务,服务之间或前端进行请求调用时,为了安全认证,可以利用OAuth2.0进行认证授权。

二. OAuth2.0核心概念(重点)

1. 核心概念

另外从上面的章节中,我们也了解到OAuth2.0的几个核心概念,如下:

  • 客户端/第三方应用: 获取用户信息如果我们使用QQ账号来登录CSDN网站,这时候CSDN相对于QQ来说就是第三方应用,或者成为是QQ的客户端。
  • 服务提供商: 对外提供请求的服务器,比如上面说的QQ。
  • Resource Owner:资源所有(拥有)者,首先我们要明确“资源”的含义,“资源”是指我们请求的各种URL接口及各种数据,这里的资源所有者,也就是登录用户。
  • Authorization Server:认证服务器,即服务提供商(比如QQ)专门用来处理认证的服务器。
  • Resource Server:资源服务器,即服务提供商存放用户资源的服务器。它与认证服务器,可以是同一台服务器,也可以是不同的服务器。
  • Access token: 访问令牌,供客户端用来请求Resource Server(API)的资源,Access token通常是short-lived短暂的。

2. 令牌与密码

在OAuth2.0中,提到了一个令牌的概念,那么令牌是什么?与我们平常所用的密码又有什么区别?其实OAuth中的令牌(token)与密码(password)作用是一样的,都可以控制用户是否可以进入系统,但是有几点不同。

  • 令牌是短期的,到期会自动失效,用户自己无法修改;密码一般是长期有效的,用户不修改,就不会发生变化。
  • 令牌可以被资源所有者撤销,会立即失效;密码一般不允许被他人撤销。
  • 令牌有一定的授权范围(scope),密码一般是完整权限。

注意:

令牌的出现,既可以让第三方应用获得权限,同时又随时可控,不会危及系统安全。但是只要知道了令牌,就能进入系统,系统一般不会再次确认身份,所以令牌必须保密,泄漏令牌与泄漏密码的后果是一样的。这也是为什么令牌的有效期,一般都设置得很短的原因。

三. OAuth2.0授权流程(重点)

了解完OAuth2.0中的各种基本概念之后,我们需要弄清楚OAuth2.0的授权流程,这样后面才能根据这个授权流程进行开发。

1. 授权流程概述

Spring Security系列教程29--OAuth2.0协议详解_服务器_05

Spring Security系列教程29--OAuth2.0协议详解_访问令牌_06编辑

OAuth 2.0的运行流程如下图,摘自RFC 6749。

Spring Security系列教程29--OAuth2.0协议详解_服务器_07

Spring Security系列教程29--OAuth2.0协议详解_客户端_08编辑

我们这里以QQ账号登录CSDN网站为例,给大家说一下OAuth2.0的授权执行流程:

(A). 某个用户(资源拥有者)打开CSDN(客户端)网站以后,CSDN(客户端)要求用户(资源拥有者)给予授权;
(B). 如果用户(资源拥有者)同意,就给予CSDN(客户端)授权;
(C). CSDN(客户端)使用上一步获得的授权,向QQ的认证授权服务器申请访问令牌Access Token;
(D). QQ的认证授权服务器对CSDN(客户端)进行认证,确认无误后,同意发放访问令牌Access Token;
(E). CSDN(客户端)使用访问令牌,向QQ的资源服务器申请获取某些受保护的资源;
(F). QQ的资源服务器确认访问令牌无误后,同意向CSDN(客户端)开放受保护的资源。

2. 授权流程详解

Spring Security系列教程29--OAuth2.0协议详解_访问令牌_09

Spring Security系列教程29--OAuth2.0协议详解_服务器_10编辑

第一步:在CSDN官网点击选择QQ登录

当我们点击选择QQ登录的图标时,实际上是向CSDN服务器发起了一个

​https://graph.qq.com/oauth2.0/show?which=Login&display=pc...&response_type=code&redirect_uri=https....passport.csdn.netogin%3FpcAuth...T​​​​ype=qq​​的请求,CSDN服务器会响应一个302重定向地址,指向QQ授权登录。这次访问会携带一个pcAuthCallback,以便QQ那边授权成功后,再次让浏览器发起对这个callback的请求,这样QQ就知道授权后要返回到哪个页面。

第二步:跳转到QQ登录页面输入用户名密码,然后点授权并登录

接着浏览器跳转到重定向地址并访问 http://www.qq.com/authorize?callback=https://yiyige.blog.csdn.net/,QQ的服务器接受到了CSDN访问的authorize,并跳转到QQ的登录页面。在用户输入账号密码点击授权并点击登录按钮后,QQ的认证服务器会对用户信息进行认证,若校验成功,该方法会响应浏览器一个重定向地址,并附上一个code(授权码)

Spring Security系列教程29--OAuth2.0协议详解_客户端_11

Spring Security系列教程29--OAuth2.0协议详解_服务器_12编辑

第三步:跳回到CSDN页面,登录成功

这一步背后的过程其实是最繁琐的,但对于用户来说是完全感知不到的。

授权QQ服务器在判断登录成功后,使页面重定向到之前CSDN发来的callback地址并附上code授权码,接着会跳转到QQ的认证服务器发起一个新的请求,获取到AccessToken令牌。获取token成功后,CSDN服务器会用拿到的token换取用户信息,最后将用户信息储存起来,并返回给浏览器其首页的视图,到此OAuth2.0授权结束。

四. OAuth2.0授权方式(重点)

讲解完了OAuth2.0的授权流程,接下来壹哥再给大家介绍另一个重要概念,即OAuth2.0的授权方式。

在RFC 6749标准中定义了获得令牌的四种授权方式(authorization grant),即 OAuth2.0 有四种获得令牌的方式,我们开发时可以选择最适合自己的那一种,向第三方应用颁发令牌,这四种授权方式如下:

  • 授权码模式(authorization code)
  • 简化模式(implicit)
  • 密码模式(resource owner password credentials)
  • 客户端模式(client credentials)

1. 授权码模式

授权码模式(authorization code),指的是第三方应用先申请一个授权码,然后再用该授权码获取访问令牌的方式。这种方式是功能最完整、流程最严密的授权模式,也是开发时最常用,安全性最高的授权模式,适用于那些有后端的 Web 应用,比如我们前面介绍的以QQ信息登录到CSDN网站上就是采用授权码模式。授权码由前端发起申请,令牌则储存在后端,而且所有与资源服务器的通信都在后端完成,这样前后端分离,可以避免令牌泄漏。授权码模式执行流程可以分为如下4步:

Spring Security系列教程29--OAuth2.0协议详解_服务器_13

Spring Security系列教程29--OAuth2.0协议详解_访问令牌_14编辑

接下来我把这4步再分开详细说明一下。

(1). 用户请求客户端A

由客户端A将用户导向认证服务器B请求授权码,假设用户同意授权,认证服务器B会将用户导向客户端A事先指定的"重定向URI"(redirection URI),同时附上一个授权码。

https://b.com/oauth/authorize?
response_type=code&
client_id=CLIENT_ID&
redirect_uri=CALLBACK_URL&
scope=read

Spring Security系列教程29--OAuth2.0协议详解_客户端_15

比如我们前面利用QQ进行登录到CSDN网站时,获取code授权码的url:

https://graph.qq.com/oauth2.0/show?which=Login
&display=pc
&client_id=100270988899
&response_type=code
&redirect_uri=https://passport.csdn.net/account/login?pcAuthType=qq
&state=test

Spring Security系列教程29--OAuth2.0协议详解_访问令牌_16

  • response_type:授权类型,必选项,为固定值code;
  • client_id: 客户端id,必选项,表示告诉 认证服务器B 是谁在发起请求;
  • redirect_uri:可选项,是 认证服务器B 接受或拒绝请求后的回调网址;
  • scope:可选项,表示要求的授权范围(这里是只读);
  • state: 客户端状态。

(2). 客户端A收到授权码code

附上之前的"重定向URI"参数,向认证服务器B申请令牌:GET /oauth/token?response_type=code&client_id=test&redirect_uri=重定向页面链接,请求成功后返回code授权码,一般有效时间是10分钟。

https://a.com/callback?code=AUTHORIZATION_CODE

Spring Security系列教程29--OAuth2.0协议详解_服务器_17

(3). 客户端A向认证服务器B发起申请令牌的请求

B会核对授权码和重定向URI,确认无误后,向客户端A返回访问令牌(access token)和更新令牌(refresh token),POST /oauth/token?response_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA&redirect_uri=重定向页面链接。

https://b.com/oauth/token?
client_id=CLIENT_ID&
client_secret=CLIENT_SECRET&
grant_type=authorization_code&
code=AUTHORIZATION_CODE&
redirect_uri=CALLBACK_URL

Spring Security系列教程29--OAuth2.0协议详解_服务器_18

(4). 认证服务器B 收到请求以后

就会颁发令牌,向redirect_uri指定的网址,发送一段 JSON 数据:

{    
"access_token":"ACCESS_TOKEN",
"token_type":"bearer",
"expires_in":2592000,
"refresh_token":"REFRESH_TOKEN",
"scope":"read",
"uid":100101,
"info":{...}
}

Spring Security系列教程29--OAuth2.0协议详解_访问令牌_19

2. 简化模式

简化模式(implicit grant type),有些 Web 应用只有前端,没有后端,这时就只能将令牌储存在前端浏览器中。所以在RFC 6749中还规定了第二种授权方式,允许直接向前端颁发令牌,因为是直接在浏览器中向认证服务器申请令牌,跳过了"授权码"这个步骤,所以称为 "隐藏(授权码)式implicit",或者被称为隐式授权模式。

隐式授权模式的客户端一般是指用户浏览器,访问令牌通过重定向的方式传递到用户浏览器中,再通过浏览器的JavaScript代码来获取访问令牌。这种授权方式的所有步骤都是在浏览器中完成,没有通过第三方应用程序的服务器,访问令牌直接暴露在浏览器端,令牌对访问者是可见的,且客户端不需要认证,所以可能会导致访问令牌被黑客获取。该模式适用于对安全性要求不高的应用中,仅适用于需要临时访问的场景。

Spring Security系列教程29--OAuth2.0协议详解_客户端_20

Spring Security系列教程29--OAuth2.0协议详解_服务器_21编辑

流程步骤:

(A). 客户端将用户导向认证服务器;
(B). 用户决定是否给于客户端授权;
(C). 假设用户给予授权,认证服务器将用户导向客户端指定的"重定向URI",并在URI的Hash部分包含了访问令牌;
(D). 浏览器向资源服务器发出请求,其中不包括上一步收到的Hash值;
(E). 资源服务器返回一个网页,其中包含的代码可以获取Hash值中的令牌;
(F). 浏览器执行上一步获得的脚本,提取出令牌;
(G). 浏览器将令牌发给客户端。

请求URL:

GET /authorize?response_type=token&client_id=s6BhdRkqt3
&state=xyz&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb

HTTP/1.1

Host: server.example.com

Spring Security系列教程29--OAuth2.0协议详解_服务器_22

与授权码模式相比,用户的登录环节是一样的,只是在授权成功之后的重定向上,授权码模式是携带一个认证码,由客户端通过认证码申请访问令牌。而隐式授权模式则直接将访问令牌作为URL的散列部分传递给浏览器,散列部分是专门用于指导浏览器行为的,比如浏览器页面定位的锚点就可以由散列属性来进行判定。

注意:

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

3. 用户名密码模式

密码模式(Resource Owner Password Credentials Grant),客户端提供一个专用页面,然后用户向客户端提供自己的用户名和密码,客户端使用这些信息,向"服务提供商"索要授权。在这种模式中,用户必须把自己的用户名密码给客户端,但是客户端不得存储密码。该授权模式适用于用户对客户端高度信任的情况下使用,一般不支持refresh token。

Spring Security系列教程29--OAuth2.0协议详解_访问令牌_23

Spring Security系列教程29--OAuth2.0协议详解_客户端_24编辑

执行步骤:

(A). 用户向客户端提供用户名和密码;
(B). 客户端将用户名和密码发给认证服务器,向后者请求令牌;
(C). 认证服务器确认无误后,向客户端提供访问令牌;

响应信息:

POST /token HTTP/1.1 
Host: server.example.com
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded
grant_type=password&username=johndoe&password=A3ddj3w

Spring Security系列教程29--OAuth2.0协议详解_访问令牌_25

注意:

用户名密码授权方式需要用户给出自己的用户名/密码,显然风险很大,因此只适用于其他授权方式都无法采用的情况,而且必须是用户高度信任的应用。

4. 客户端模式

客户端模式,指客户端以自己的名义,而不是以用户的名义,向"服务提供商"发起认证。严格地说,客户端模式并不属于OAuth2.0框架所要解决的问题。在这种模式中,用户直接向客户端注册,客户端以自己的名义要求"服务提供商"提供服务,其实不存在授权问题。

客户端授权模式通常是由客户端提前向授权服务器申请应用公钥、私钥,并通过这些关键信息向授权服务器申请访问令牌,从而得到资源服务器提供的资源,比如常见的微信公众平台、支付宝支付平台授权等。该模式适用于没有前端的命令行应用中,即在命令行下请求令牌。

Spring Security系列教程29--OAuth2.0协议详解_服务器_26

Spring Security系列教程29--OAuth2.0协议详解_访问令牌_27编辑

执行步骤:

(A). 客户端向认证服务器发起身份认证,并要求一个访问令牌;
(B). 认证服务器确认无误后,向客户端提供访问令牌。

A步骤中,客户端发出的HTTP请求,包含以下参数:

  • granttype:表示授权类型,此处的值固定为"clientcredentials",必选项。
  • scope:表示权限范围,可选项。

响应信息:

POST /token HTTP/1.1
Host: server.example.com

Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials

#grant_type参数等于client_credentials表示采用凭证式,
#client_id和client_secret用来让 B 确认 A 的身份

Spring Security系列教程29--OAuth2.0协议详解_客户端_28

注意:

这种方式给出的令牌,是针对第三方应用的,而不是针对用户的,即有可能多个用户共享同一个令牌。

希望通过本文的介绍,可以让你对OAuth2.0协议有所掌握,后面我们可以把Spring Security与OAuth2.0结合,实现更灵活的认证授权。


标签:QQ,令牌,--,Spring,29,服务器,授权,OAuth2.0,客户端
From: https://blog.51cto.com/u_7044146/5967097

相关文章

  • Pu’er Tea: 10 Benefits You’t Don’t Know About
    Pu'ertea.WhataretheeffectsandeffectsofdrinkingPu'ertea?FirstBenefitofDrinkingPu'erteaLipidreduction,weightloss,bloodpressure,anti-arterios......
  • AcWing1134/洛谷P1144 最短路计数
    AcWing传送门洛谷传送门题目大意\(\qquad\)给一个无向图,边权都是\(1\),求出以\(1\)为源点,到各个点(\(1\simn\))的最短路数量解题思路\(\qquad\)边权都是\(1\)的图中最......
  • C/C++编译器配置——MinGW下载安装
    C/C++编译器配置——MinGW下载安装前言本文主要讲述如何安装C语言编译器——MinGW,特点是文章附有完整详细的实际安装过程截图,文字反而起说明提示作用。编写本文的原因......
  • 解决pipline找不到docker命令:/Users/beck/.jenkins/workspace/locust_test@tmp/durabl
    问题一:/Users/beck/.jenkins/workspace/locust_test@tmp/durable-884e1b18/script.sh:line1:docker:commandnotfound完整的pipeline如下,在dockerhub上我打包了locu......
  • 安全智能分析技术 定义内涵
    安全分析工作流定制工作流(Workflow)是对工作流程及其各操作步骤之间业务规则的抽象、概括描述。工作流系统是以规格化的流程描述作为输入的软件组件,它维护流程的运行状态,并......
  • 实验六 文件应用编程
    实验任务4#define_CRT_SECURE_NO_WARNINGS#include<stdlib.h>#include<stdio.h>intmain(){charch;intcount=0;FILE*fp;fp=fopen("data......
  • linux的journalctl使用
    什么是journaldjournald是systemd的守护程序,该守护程序从各种日志源(例如syslog)收集日志。journalctl是使您可以与日记日志进行交互的命令行工具。使用journalctl,您可以读取......
  • 基于K-means聚类算法进行客户人群分析
    摘要:在本案例中,我们使用人工智能技术的聚类算法去分析超市购物中心客户的一些基本数据,把客户分成不同的群体,供营销团队参考并相应地制定营销策略。本文分享自华为云社区《​......
  • 4.面向对象编程(上)
    学习面向对象内容的三条主线Java类及类的成员面向对象的三大特征其它关键字一、面向过程与面向对象面向过程(POP)与面向对象(OOP)面向过程,强调的是功能行为,以函数为最小......
  • 信息安全标准重要性
    写在前面早年刚参加信息安全工作更多的学点皮毛技术,到处找安全工具,跟踪poc,拿到一个就全网扫一遍,从来没有想过,系统化的安全工作应该怎样搞?我做的工作在安全体系中处于哪个阶......