| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 系统运维 -> OAuth2的运行机制(GitHub单点登录) -> 正文阅读 |
|
[系统运维]OAuth2的运行机制(GitHub单点登录) |
1、OAuth2框架简介??在大多数情况下,OAuth2被称为授权框架(或规范框架),其主要目的是允许第三方网站或应用程序访问资源。有时人们也把OAuth2称为一项委托协议。这里将介绍如何实现OAuth2与SpringBoot和Spring Security的集成应用。 ??我们以前使用的是HTTP Basic身份言则会那个,它有以下两个问题:
??为每个请求发送凭据可能只适用于隔离环境的情况,但这通常是不可取的,因为这意味着:
??我们希望在应用程序的架构中去掉这两点,因为它们会使凭据编程漏洞,从而削弱安全性。通常,我们会希望有一个单独的系统管理系统用户凭据。假设我们必须为组织中使用的所有应用程序配置和使用单独的凭据。如下图 ??如果将凭据管理的职责隔离在系统的一个组件中会更好。目前,我们将其称为授权服务器。 2、OAuth2身份验证架构中的组件OAuth2组件包括:
3、使用OAuth2的实现选项??OAuth2主要是指使用令牌进行授权。令牌就像门禁卡一样。一旦获得令牌,就可以访问特定的资源。但是OAuth2提供了多种可能性以便获取令牌也称为授权。以下是可以选择的最常见的OAuth2授权方式。
3.1 实现授权码授权类型这种授权类型是最常用的OAuth2流程之一。 以下是授权码授权类型的工作方式。接下来将详细深入讲解每个步骤的细节。 (1)发出身份验证请求。 (2)获取访问令牌。 (3)调用受保护的资源。 步骤1:使用授权码授权类型发出身份验证请求 ??客户端将用户重定向到需要进行身份验证的授权服务器端点。假设我们正在使用应用程序X,并且需要访问一个受保护的资源。为了访问该资源,应用程序X需要我们进行身份验证。它会打开一个授权服务器上的页面,其中包含登录表单,我们必须用凭据填写该表单。
??从技术上讲,这里发生的处理是,当客户端将用户重定向到授权服务器时,客户端会调用授权端点,并在请求中使用以下详细信息。
??身份验证成功后,授权服务器将根据重定向URI回调客户端,并提供授权码和状态值。客户端要检查状态值是否与它在请求中发送的状态值相同,以确认不是其他人试图调用重定向URI。之后客户端会使用授权码获取第(2)步中所示的访问令牌。 步骤2:使用授权码授权类型获取访问令牌 ??为了允许用户访问资源,第(1)步所产生的授权码就是经过身份验证的用户的客户端证明。没错,这就是它被称为授权码类型的原因。现在客户端将使用该授权码调用授权服务器以获取令牌。 ??提示:在第(1)步中,交互发生在用户和授权服务器之间。而在这个步骤中,交互是在客户端和授权服务器之间进行的。 ??从技术上讲,客户端现在会向授权服务器发出请求。该请求包含以下详细信息:
??作为响应,服务器会返回一个access_token。这个令牌是一个客户端可用来调用由资源服务器暴露的资源的值。 步骤3:使用授权码授权类型调用受保护资源 ??从成功地从授权服务器获得访问令牌之后,客户端现在就可以调用受保护的资源了。在调用资源服务器的端点时,客户端要在授权请求头中使用访问令牌。 3.2 使用密码授权类型??此授权类型也被称为资源所有者凭据授权类型。使用此流程的应用程序会假定客户端收集用户凭据,并使用这些凭据进行身份验证,然后从身份验证服务器获得访问令牌。 步骤1:使用密码授权类型时请求访问令牌 ??使用密码授权类型,流程会简单很多。客户端会收集用户凭据并调用授权服务器来获取访问令牌。当请求访问令牌时,客户端还会在请求中发送以下详细信息:
??客户端在响应中接收回一个访问令牌。接下来客户端就可以使用该访问令牌调用资源服务器的端点。 步骤2:使用密码授权类型时,需要使用访问令牌调用资源 ??一旦客户端有了访问令牌,它就可以使用该令牌调用资源服务器上的端点,这与授权码授权类型完全相同。客户端要在授权请求头中将访问令牌添加到请求。 ??提示:密码授权类型比授权码授权类型更不安全,主要是因为其前提是要与客户端应用程序共享用户凭据。 3.3 实现客户端凭据授权类型??这是OAuth2所描述的最简单的授权类型。可以再用户不参与的情况下使用它:也就是说,在两个应用程序之间实现身份验证时不需要用户参与。可以讲客户端凭据授权类型看做密码授权类型和API密钥身份验证流程的组合。 ??客户端凭据授权类型的步骤与密码授权类型类似。唯一的例外是对访问令牌的请求不需要任何用户凭据。以下是实现这一授权类型的步骤: 步骤1:使用客户端凭据授权类型请求访问令牌 ??为了获得访问令牌,客户端要向授权服务器发送一个包含以下详细信息的请求。
??作为响应,客户端将接收到一个访问令牌。接下来客户端可以使用该访问令牌调用资源服务器的端点。 步骤2:使用客户端凭据授权类型时,可访问令牌调用资源 ??一旦客户端有了访问令牌,它就可以使用该令牌调用资源服务器上的端点,这与授权码授权类型和密码授权类型完全相同。客户端要在授权请求头中将访问令牌添加到请求。 3.4 使用刷新令牌获得新的访问令牌??假设在应用程序中实现了永不过期的令牌。这意味着客户端可以一次又一次地使用相同的令牌调用资源服务器上的资源。那么如果令牌被偷了,该怎么办?最后,不要忘记令牌作为一个简单的HTTP头信息被附加在每个请求上。如果令牌没有过期,得到令牌的人就可以使用它访问资源。不会过期的令牌太强大了。它变得几乎和用户凭据一样强大。应该避免这种情况,并缩短令牌的生命周期。这样,过期的令牌就不能再使用了。客户端必须获得另一个访问令牌。 ??要获得新的访问令牌,客户端可以根据所使用的的授权类型重新运行流程。例如,如果授权类型是身份验证授权码,则客户端会将用户重定向到授权服务器登录端点,用户必须再次填写他们的用户名和密码。这对用户不太友好,是吗?假设这个令牌的生命周期只有20分钟,而用户在这个在线应用程序上工作了两个小时。那么在这段时间里,这个应用程序会将用户重定向回去6次,以便再次登录。为了避免重新进行身份验证,授权服务器可以发出刷新令牌,它的值和用途与访问令牌不同。应用程序使用刷新令牌获得一个新的访问令牌,而不必重新进行身份验证。 ??如何使用刷新令牌,从哪里获得刷新令牌,当使用授权码或密码授权类型等流程时,授权服务器将返回一个刷新令牌和一个访问令牌。对于客户端凭据授权,则不存在刷新令牌,因为此流程不需要用户凭据。一旦客户端有了一个刷新令牌,那么当访问令牌过期时,客户端应该发出一个包含以下详细信息的请求。
??为了响应此请求,授权服务器会发出一个新的访问令牌和一个新的刷新令牌。 4、实现一个简单的单点登录应用程序??这里将实现一个带有Spring Boot和Spring Security的OAuth2框架的应用程序。单点登录(SSO)应用程序是通过授权服务器进行身份验证的应用程序,然后将使用刷新令牌让用户保持登录状态。在我们的示例中,它只代表来自OAuth2架构的客户端。 ??在这个应用程序中,我们要是用GitHub作为授权和资源服务器,并重点关注使用授权码授权类型的组件之间的通信。 4.1 管理授权服务器?? ??如何使用GitHub这样的第三方作为授权服务器呢?这意味着,最终,我们的应用程序不会管理它的用户,任何人都可以使用他们的GitHub账户登录到我们的应用程序。与其他授权服务器一样,GitHub需要知道它要向哪个客户端应用程序发出令牌。因此,OAuth应用程序必须向GitHub授权服务器进行注册。为此,需要使用以下链接完成一个简短的表单。 ??当添加一个新的OAuth应用程序时,需要为应用程序指定一个名称,还要制定主页以及GitHub将对应用程序进行回调的链接。可以允许这样处理的OAuth2授权类型是授权码类型。这个授权类型的假设前提是,客户端会将用户重定向到授权服务器(本示例中是GitHub)以进行登录,然后授权服务器通过一个预定义的URL回调客户端。这就是需要在这里标识回调URL的原因。因为是我们自己的系统上运行示例,所以在这两种情况下都使用了本地主机(localhost)。并且由于没有更改端口(默认端口8080),这将使http://localhost:8080成为主页的URL。对于其回调使用相同的URL。
??一旦填写了该表单并选择Register application,GitHub就会为我们提供客户端ID和客户端密钥信息。 ??这个配置就是需要为授权服务器做的所有处理。现在我们有了客户端凭据,可以开始处理应用程序了。 4.2 开始实现??这里要实现一个SSO应用程序。创建一个新的Spring Boot应用程序,并将以下依赖添加到pom.xml文件中。
??首先要确保某些东西的安全:一个网页。为此,要创建一个控制器类和一个表示应用程序的简单HTML页面。 4.2.1 控制器类
4.2.2 main.html??SpringBoot项目的resources/static文件夹中定义了main.html页面。它只包含标题文本,所以在访问页面时会观察到以下信息。 4.3.3 配置类??接下来设置安全配置,以允许应用程序使用GitHub登录。首先要编写一个配置类。这里扩展了WebSecurityConfigurerAdapter并重写了configure(HttpSecurity http)方法。现在有一个不同之处:此处调用了另一个名为oauth2Login()的方法。
??oauth2Login()只是将一个新的身份验证过滤器添加到过滤器链中。当调用oauth2Login()方法时,框架添加到过滤器链中的过滤器是OAuth2LoginAuthenticationFilter。这个过滤器会拦截请求,并应用OAuth2身份验证所需的逻辑。 4.3 实现ClientRegistration??这里讨论如何实现OAuth2客户端和授权服务器之间的链接。如果想让应用程序真正做一些事情,这是至关重要的。如果现在就启动该应用程序,那么将无法访问主页。无法访问主页的原因是由于制定了对于任何请求,用户都需要进行身份验证,但是这里还没有提供任何身份验证方法。我们将GitHub确立为授权服务器。为此,Spring Security定义了ClientRegistration接口。 ??ClientRegistration接口表示OAuth2架构中的客户端。对于该客户端,需要定义其所需的所有详情,其中包括:
4.3.1 创建一个ClientRegistration实例
??第一眼看上去要设置的东西有点多,但它只不过是设置客户端ID和密钥而已。此外,还定义了作用域(授予的权限)、客户但名称和所选择的注册ID。除了这些信息,还必须提供授权服务器的URL。
??这些URI是从那里获得的?如果授权服务器不是有我们开发的,则需要从说明文档中获取它们。以GitHub为例,可以在这里找到它们: https://docs.github.com/cn/developers/apps/building-oauth-apps/authorizing-oauth-apps ??不过别急!Spring Security比这更智能。该框架定义了一个名为CommonOAuth2Provider的类。这个类部分定义了可以用于身份验证的最常见提供程序的ClientRegistration实例,其中包括:
如果使用这些提供程序之一, 那么可以按照如下代码所示定义ClientRegistration
??如上所示,这样更为清晰,并且我们不必手动查找和设置授权服务器的URL。当然,这只适用于公共提供程序。如果授权服务器不在公共提供程序之列,则只能完全定义ClientRegistration,代码如下所示 4.3.2 在配置类中构建ClientRegistration对象
4.4 实现ClientRegistrationRepository??这里介绍如何为Spring Security注册用于身份验证的ClientRegistration实例。上面介绍了如何通过实现ClientRepository接口来表示Spring Security的OAuth2客户端。但是还需要对其进行设置,以便将其用于身份验证。为此,Spring Security实用了类型为ClientRegistrationRepository对象。 ??ClientRegistrationRepository接口类似于前面介绍过的UserDetailsService接口。与UserDetailsService对象通过其用户名查找UserDetails相同,ClientRegistrationRepository对象通过其注册ID查找ClientRegistration。 ??可以实现ClientRegistrationRepository接口来告知框架在哪里找到ClientRegistration实例。Spring Security为ClientRegistrationRepository提供了一个实现,该实现会将ClientRegistration的实例存储在内存中,也就是InMemoryClientRegistrationRepository。 ??为了完成该应用程序实现,这里使用InMemoryClientRegistrationRepository实现定义了一个ClientRegistrationRepository,并在Spring上下文中将其注册为一个bean。这里还将构建的ClientRegistration实例添加到InMemoryClientRegistrationRepository中,这是通过将其作为InMemoryClientRegistrationRepository构造函数的参数来完成的。 4.5.1 注册ClientRegistration对象
4.5 获取经过身份验证的用户的详细信息??在Spring Security架构中,是SecurityContext在存储经过身份验证的用户的详细信息。身份验证过程结束后,负责此处理的过滤器会将Authentication对象存储在SecurityContext中。应用程序可以从中获取用户详细信息,并在需要时使用它们。OAuth2身份言则会那个也会进行相同的处理。 ??在本示例中,框架所使用的Authentication对象的实现的名称为OAuth2AuthenticationToken。可以直接从SecurityContext中获取它,或者让Spring Boot将它注入端点的一个参数中。 4.5.1 使用登录用户的详细信息
4.6 测试应用程序??首先确保没有登录到GitHub,还要确保打开了一个浏览器控制台来检查请求导航的历史记录。这个历史记录会提供OAuth2流程中所发生的的步骤的概述如果用户已通过身份验证,那么应用程序将直接记录该用户。然后需要启动应用程序,在浏览器中访问应用程序主页。 启动应用程序 访问:http://localhost:8080 可以看到,应用程序会将我们重定向如下所示的URL。 https://github.com/login/oauth/authorize?response_type=code&client_id=9057d643ec6beaecbd13&scope=read:user&state=74bPx6vLhVSvCsG2ysKCrwsPpajMpZCb8yKJF6a3jJE=&redirect_uri=http://localhost:8080/login/oauth2/code/github。这个URL在CommonOauth2Provider类中被配置为GitHub的授权URL。 该应用程序会降所需的查询参数附加到URL。这些参数是:
??使用GitHub凭据并使用GitHub登录到应用程序。用户将通过身份验证并被重定向回来,如下图所示。 ??下面的代码片展示了GitHug将用户重定向回应用程序所调用的URL。可以看到,GitHub提供了应用程序用来请求访问令牌的授权码。 http://localhost:8080/login/oauth2/code/github?code=71092d9c1ddff55b6dc4&state=Qs-IbT0ngFpNWxQIsKPKrkCElXdUHW_zgZ7Zahs8Iec= ??在此不会看到浏览器对令牌端点的调用,因为这是直接在应用程序中发生的。但是可以相信应用程序已经设法获得了一个令牌,因为我们可以看到在控制台中打印的用户详细信息。这意味着应用程序会设法调用端点来检索用户详细信息。以下代码片段展示了这个输出的一部分。 Principal: Name: [66518135], Granted Authorities: [[ROLE_USER, SCOPE_read:user]], User Attributes: [{login=xiongtete0519, id=66518135, node_id=MDQ6VXNlcjY2NTE4MTM1, avatar_url=https://avatars.githubusercontent.com/u/66518135?v=4, gravatar_id=, url=https://api.github.com/users/xiongtete0519, html_url=https://github.com/xiongtete0519, followers_url=https://api.github.com/users/xiongtete0519/followers, following_url=https://api.github.com/users/xiongtete0519/following{/other_user}, gists_url=https://api.github.com/users/xiongtete0519/gists{/gist_id}, starred_url=https://api.github.com/users/xiongtete0519/starred{/owner}{/repo}, subscriptions_url=https://api.github.com/users/xiongtete0519/subscriptions, organizations_url=https://api.github.com/users/xiongtete0519/orgs, repos_url=https://api.github.com/users/xiongtete0519/repos, events_url=https://api.github.com/users/xiongtete0519/events{/privacy}, received_events_url=https://api.github.com/users/xiongtete0519/received_events, type=User, site_admin=false, name=xiongtete, company=null, blog=, location=null, email=null, hireable=null, bio=null, twitter_username=null, public_repos=45, public_gists=0, followers=1, following=2, created_at=2020-06-06T11:51:28Z, updated_at=2022-02-26T11:05:33Z, private_gists=0, total_private_repos=0, owned_private_repos=0, disk_usage=6387, collaborators=0, two_factor_authentication=false, plan={name=free, space=976562499, collaborators=0, private_repos=10000}}]; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@ffff4c9c: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: 83FC7D79793146B3CB22797B661F7A89; Granted Authorities: ROLE_USER, SCOPE_read:user 5、总结
|
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/16 3:16:44- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |