鸽了很久,其实也因为自己确实比较忙,加之自己在造demo的时候也遇到了很多问题,并且网上这方面的解答非常之少,不过也正是因为少,才更加让我想写这样的知识分享,最终,在一篇博客的解答下解决了问题,本节我们就开始Oauth2的学习。在之前的学习中,我们可以说SpringSecurity本身的基础学习差不多告一段落,大家已经可以通过自己的能力去搭建一个SpringSecurity的安全应用。
那么接下来我们就接着学习OAuth2这样一个庞大的主题,我们在这一章主要介绍一个概要,即OAuth2是什么,然后将会把它应用到一个关注使用单点登录(SSO)进行身份验证的应用程序上。这里之所以选用SSO,是因为其非常简单,也非常有用。
在大多数情况下,OAuth2被称为授权框架(或规范框架),其主要目的是允许第三方网站或应用程序访问资源。有时人们也把OAuth2称为一项委托协议。无论如何称呼它,重要的是要记住OAuth2不是一个特定的实现或库。也可以将OAuth2流程定义应用于其他平台、工具或语言。这里将介绍如何实现OAuth2与SpringBoot和Spring Security的集成应用。
理解OAuth2我们可以通过和之前学习过的HTTP Basic身份验证方法进行对比,我们以前使用的是HTTP Basic身份言则会那个,它有以下两个问题:
为每个请求发送凭据可能只适用于隔离环境的情况,但这通常是不可取的,因为这意味着:
我们希望在应用程序的架构中去掉这两点,因为它们会使凭据变成漏洞,从而削弱安全性。通常,我们会希望有一个单独的系统管理系统用户凭据。假设我们必须为组织中使用的所有应用程序配置和使用单独的凭据。如下图:在组织中,通常会使用多个应用程序。其中大多数需要用户进行身份验证才能使用。用户需要记住多个密码,组织要管理多个凭据集合,这将是一项挑战。
如果将凭据管理的职责隔离在系统的一个组件中会更好。目前,我们将其称为授权服务器。如下图:它拥有更易于维护的架构会将凭据单独保存,并允许所有应用程序为其用户使用同一组凭据。
这种方式消除了表示同一个人的重复凭据。通过这种方式,架构将变得简单。
OAuth2主要是指使用令牌进行授权。令牌就像门禁卡一样。一旦获得令牌,就可以访问特定的资源。但是OAuth2提供了多种可能性以便获取令牌也称为授权。以下是可以选择的最常见的OAuth2授权方式。
这种授权类型是最常用的OAuth2流程之一。
如上图,授权代码授权类型。客户端会要求用户直接与授权服务器交互,以便为其授予用户请求的权限。在授权之后,授权服务器会发出令牌,这样客户端就可以使用该令牌访问用户的资源。
ps:上图中的箭头不一定表示HTTP请求和响应。这些箭头表示OAuth2的参与者之间交换的消息。例如,当客户端告知用户“告知授权服务器你允许我做这个操作”时,客户端就会将用户重定向到授权服务器登录页面。当授权服务器向客户端提供访问令牌时,授权服务器实际上会根据所谓的重定向URI来调用客户端。当然这些细节后面会讲到,这里只需知道这些序列图不仅仅表示HTTP请求和响应,它们是对OAuth2参与者之间通信的简化描述
以下是授权码授权类型的工作方式。接下来将详细深入讲解每个步骤的细节。
(1)发出身份验证请求。
(2)获取访问令牌。
(3)调用受保护的资源。
客户端将用户重定向到需要进行身份验证的授权服务器端点。假设我们正在使用应用程序X,并且需要访问一个受保护的资源。为了访问该资源,应用程序X需要我们进行身份验证。它会打开一个授权服务器上的页面,其中包含登录表单,我们必须用凭据填写该表单。
ps:这里真正需要注意的是,用户会直接与授权服务器交互。用户不会向客户端应用程序发送凭据
从技术上讲,这里发生的处理是,当客户端将用户重定向到授权服务器时,客户端会调用授权端点,并在请求中使用以下详细信息。
https://gitee.com/oauth/authorize?response_type=code&client_id=c70egngnghhn464541b580db179d027df1f3017797e053890edd&scope=user_info&state=x5dLt6OkIRluOTVN4UQXG4mds5tqJBokhAd140_nqog%3D&redirect_uri=http://localhost:9090/login/oauth2/code/gitee
大家对比一下就会发现和上面的元素是一样的
身份验证成功后,授权服务器将根据重定向URI回调客户端,并提供授权码和状态值。客户端要检查状态值是否与它在请求中发送的状态值相同,以确认不是其他人试图调用重定向URI。之后客户端会使用授权码获取第(2)步中所示的访问令牌。
为了允许用户访问资源,第(1)步所产生的授权码就是经过身份验证的用户的客户端证明。没错,这就是它被称为授权码类型的原因。现在客户端将使用该授权码调用授权服务器以获取令牌。
PS:在第一步中,交互发生在用户和授权服务器之间。而在这个步骤中,交互是在客户端和授权服务器之间进行的
你可能会好奇,为什么流程需要对授权服务器进行两次调用并且得到两个不同的令牌——授权码和访问令牌。花点时间理解这一点:
那么授权服务器为什么不直接返回访问令牌呢?OAuth2定义了一个被称为隐式授权类型的流程,授权服务器会在其中直接返回访问令牌。该隐式授权类型后面不会去进行讲解,因为不建议使用,而且如今大多数授权服务器都不允许使用。授权服务器将使用访问令牌直接调用重定向URI,而不会确保接收该令牌的确实是正确的客户端,这一简单事实会降低流程的安全性。通过首先发送授权码,客户端必须再次使用其凭据来证明其身份,以便获得令牌。客户端会进行最后一次调用以获取访问令牌并在其中发送:
从技术上讲,客户端现在会向授权服务器发出请求。该请求包含以下详细信息:
作为响应,服务器会返回一个access_token。这个令牌是一个客户端可用来调用由资源服务器暴露的资源的值。
在成功地从授权服务器获得访问令牌之后,客户端现在就可以调用受保护的资源了。在调用资源服务器的端点时,客户端要在授权请求头中使用访问令牌。
我将接口所经历的步骤总结成下图:
客户端从进行第三方认证操作的起点,默认格式为{baseUrl}/oauth2/authorization/{clientRegistrationId},其中clientRegistrationId代表着一个第三方标识,可以是微信、支付宝等开放平台,这里为gitee。用户点击了这个请求后就开始了授权之旅。
也就有了客户端向客户重定向的第②步,然后第⑤步就是向授权服务器(gitee)去获取授权码,然后用户通过认证同意授权后,授权服务器将客户重定向到通过配置的发回授权码的redirectUri发回授权码,
用户此时通过这个Url将授权码发给了客户端,客户端通过该授权码通过⑩请求获取accessToken
那么更详细的,也是我参考过觉得不错的文章有下面2篇,大家可以去看一下:
https://blog.csdn.net/longlivechina008/article/details/125007457
https://www.cnblogs.com/felordcn/p/13952072.html
其中上图中Client客户端中的OAuthFilter相当于之前SpringSecurity流程中的AuthenticationManager->AuthenticationProvider->UserDetailsService层层返回UserDetails到Filter,然后Filter将UserDetails打包为Authentication然后放到SecurityContext安全上下文中供后续使用,然后结束filterChain到达。
授权码是使用频率非常高的一种授权类型,大家需要好好吸收,尤其是概念,后面我们还会通过授权码授权类型的一个实例-sso单点登录去让大家印象更加深刻。
授权码授权类型的最大优点是让用户可以允许客户端执行特定的操作,而不需要与客户端共享其凭据,不过,这种授权类型有一个缺点:如果有人截获授权码,会发生什么?当然,如之前所属,客户端需要使用其凭据进行身份验证。但是,如果客户端凭据也以某种方式被盗了呢?即使这种情况非常罕见,但是我们也可以认为它是这种授权类型的漏洞。要避免这个漏洞,就需要借助PKCE授权码授权类型所提供的更复杂的场景,大家有兴趣可以自行了解。
上一篇: 高中教师对学生评语
下一篇: 学生思想品德鉴定优秀评语