如何使用 Spring Boot + Angular 处理外部 OAuth2 身份验证
Posted
技术标签:
【中文标题】如何使用 Spring Boot + Angular 处理外部 OAuth2 身份验证【英文标题】:How to handle an External OAuth2 auth with Spring Boot + Angular 【发布时间】:2019-05-22 19:05:19 【问题描述】:我有一个 Spring Boot 应用程序作为后端和一个 Angular 6 前端。它们分别工作得很好,我使用this guide 作为起点。我现在要使用外部 OAuth 对我的用户进行身份验证,以访问他们的一些《魔兽世界》角色数据。
我对如何使用 OAuth 限制对后端的访问有一个不错的想法,因为 Spring Security 使这非常容易。我正在努力解决的问题是,如果我的用户经过身份验证 + 有权访问字符 A,我该如何在前端 和 后端处理这个问题?
由于 Angular 正在处理 html 页面的路由,并且这些 HTML 页面调用我的后端,我不确定如何将授权扩展到 Angular。我可以展示代码,但我认为这更像是一个概念问题而不是代码问题。
【问题讨论】:
您打算使用哪个 OAuth 提供程序?您正在使用什么 Angular OAuth 库(如果有的话)?你有 JWT 还是只是裸令牌?您打算使用哪个 OAuth 流程?使用其中一个概念没什么大不了的,但这有点取决于您的详细信息。 我基本上只是在验证暴雪的 OAuth。我在 Angular 方面没有挑选任何东西,所以我想这就是我要问的......我是否需要为 Angular 和 Spring 提供单独的 OAuth 库? 是的,当然。 Angular 不知道 Spring 是什么 :) 无论如何。我可以试着举个例子,等待答案。 【参考方案1】:你需要给你的前端代码一些 OAuth 的爱。例如this 是一个很好的库(我使用它),但是 YMMW。
现在,长答案:
OAuth 规范定义了几种不同的“流”,客户端应用程序常用的一种是隐式流。这意味着,如果您想使用 vanilla,请自己实现,您需要执行以下操作:
-
页面加载时:检查 URL 状态。如果找到令牌和数据,请将它们存储在 sessionStorage 中。
如果 URL 中没有令牌,请检查 sessionStorage 中的令牌。
对您的后端的每个 HTTP 请求,您都将 accessToken 附加到标头中。
对于登录/注销,您需要使用专门设计的 URL 和参数将用户重定向到 OAuth 服务器。
现在更长的答案:
-
在页面加载时,检查您是否有一些状态,例如 sessionStorage。比如,保存的
accessToken
或类似的东西。 (不完全是,但请继续阅读)。
如果是,您可能想在 OAuth 服务器上验证此令牌(有时您还会将过期时间戳保存在存储中,您也可以检查那个)。
在对后端的任何 Http 请求中,将此令牌(accessToken
或有时是 id_token
,或者它可能是 jwt、不记名等,我们只是说令牌)附加到 headers每一个请求。通常它类似于Authentication
标头,其值为Bearer $ token
。
后端现在可以检查此令牌,如果有效,则返回您的数据,如果无效或丢失,则返回 401。(它也可以重定向到身份验证服务器,但请不要这样做)。李>
如果页面加载时没有 标记,您可以向用户指出这一点。比如,请他们登录。
此登录按钮将将用户重定向到 OAuth 登录页面。他们离开你的页面。这是一个特制的 URL,提供您的应用数据,例如 http://server/auth/your-app-name?clientId=your-client-id&redirectUrl=http://your-angular-page/where-you-wanna-land
。这看起来如何,取决于服务器到服务器,实施到实施。
现在用户登陆他们的登录页面,提供他的用户名/密码/权限等(或者如果他们已经在那里登录,mgiht 立即重定向回来)。在他们登录并授予您的应用权限后,身份验证服务器将用户重定向回来。
现在您回到了第 1 步。但您首先要检查 URL,而不是检查 sessionStorage
。
因为 url 看起来像:http://your-angular-page/your-route?accessToken=<some_token>&...
和其他类似的东西。现在您读取 accessToken 并将其存储在本地,您就完成了。
【讨论】:
哇!这有很大帮助。我会试一试所有这些信息,谢谢!! 我有一个简短的问题@Zlatko,Battle.Net/Blizzard OAuth API 返回一个授权码。这是我用来在前端/后端之间传递的代码吗? 嗯,取决于他们使用什么 - 可能是您需要的访问令牌。或者,该代码现在用于获取实际令牌。别问,我知道这很复杂。这就是为什么最好简单地使用我链接到的库之类的东西,为你处理所有的废话。 所以实际上看起来有点混乱。似乎 angular-oauth2-oidc 库doesn't handle such a flow。由于客户端 ID 和秘密共享,暴雪还在客户端上 doesn't recommend using the code flow。但是,现在我不知道如果服务器调用 OAuth API,服务器将如何告诉客户端显示 Battle.Net 登录页面? Nonono,该库支持隐式流。您只需将用户重定向到 blizard 以进行身份验证,然后取回令牌。以上是关于如何使用 Spring Boot + Angular 处理外部 OAuth2 身份验证的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Spring-Boot 播种 Spring-Security
如何使用 graphql-spring-boot 向 GraphQL Java 添加检测?
如何在 spring-boot 中禁用 spring-data-mongodb 自动配置
如何从另一个新的 Spring Boot 项目调用一个 Spring Boot 项目中存在的 Spring Boot api