使用 Java Spring Rest Api 执行授权码授予流程

Posted

技术标签:

【中文标题】使用 Java Spring Rest Api 执行授权码授予流程【英文标题】:Execute an Authorization Code Grant Flow Using Java Spring Rest Api 【发布时间】:2020-09-18 15:15:21 【问题描述】:

我正在尝试使用 Java spring rest Api 调用需要授权的第 3 方端点,因此我需要执行授权代码授予流程。

我了解我需要首先获取代码然后将代码交换为 JWT 并最后使用 JWT 的流程能够进行安全呼叫。

对我来说没有意义的是,当我仅使用没有 UI 的后端 rest api 时,我应该如何设置重定向 URI。通常,用户会被重定向到登录页面,在那里他们可以使用用户名/密码或第 3 方帐户(google/facebook ...)登录

经过大量谷歌搜索,所有搜索都以指南结束,以保护我自己的端点,而不是从我的 Spring Boot 服务访问安全端点

编辑:值得一提的是,在@Partha 发表评论后,我只使用了一个没有任何前端(或 MVC)的后端:

首先,我添加了一个新的登录端点,当通过浏览器访问时(这不适用于 swagger/postman),它应该将用户重定向到授权服务器:

@GetMapping
public void login(HttpServletResponse httpServletResponse) 
    httpServletResponse.setHeader("Location", getAuthServerEndpoint());
    httpServletResponse.setStatus(302);

我在哪里构建了端点以获取所需的所有数据(client_id、redirect_uri...),所以它看起来像

https://idpserver.bla/oauth/authorize?client_id=xyz&redirect_uri=http://localhost:8080/token&response_type=code&scope=xyz

现在它会将我发送到身份验证服务器的登录页面,在我登录后,我希望它会将我重定向到 localhost/token(这是一个 get 请求,它将检索代码并执行一个 post 请求以获取 jwt并保存它)但是相反,我收到了无效的重定向 uri,我真的不确定这是我的实现还是服务器的问题

EDIT2:我犯了一个愚蠢的错误,没有在身份验证服务器中添加http://localhost:8080/token 作为重定向网址,因为我认为我不需要

【问题讨论】:

【参考方案1】:

不太确定您是如何尝试的.. 这里的想法是.. 您的 api 服务器应该有一个 get 端点 /login。在您的 /login 控制器中,您应该重定向到 IDP 说 http://idpserver.bla?client_id=xxx&grant_type=code&nonce=yyy&redirect_uri=http://localhost:8080/token (注​​意,它的重定向,而不是发出 api 请求)。因此,当您在浏览器中点击http://localhost:8080/login 时,您应该会看到它被重定向到 IDP。现在您输入您的凭据,IDP 会验证并重定向回http://localhost:8080/token?code=XYZABC 或类似的东西。 /token API 的控制器代码应该从 url 参数读取代码。并根据您的范围向 IDP 调用(这是 api 调用,而不是重定向)以交换令牌(idToken / accessToken)的代码。并且使用令牌,您应该能够访问受保护的资源。希望有帮助

【讨论】:

当我尝试重定向时, (public void method(HttpServletResponse httpServletResponse) httpServletResponse.setHeader("Location", idpUrl); httpServletResponse.setStatus(302); ) 我得到一个错误发生了包含的重定向 uri 无效。我不确定这是我的问题还是他们的问题。在旁注中,我需要在 url 中转义什么吗? (字符明智) IDP 要求输入用户名和密码,正确插入后,显示重定向 uri 无效的错误...我的 uri:idpserver.bla/oauth/… 是的,这意味着当您在 IDP 中注册客户端时,您将提供一个或多个重定向 URL。现在,在使用时,您应该只使用其中一个重定向 url,否则它会说无效。【参考方案2】:

根据您使用的是 MVC 还是 Webflux,将需要不同的方法:

MVC:包括一个“安全过滤器”来做到这一点。您将能够在以下链接中看到一个示例:

MVC Securiry Manager

MVC Security Filter

MVC Security Configuration

Webflux:配置您自己的安全管理器。您将能够在以下链接中看到一个示例:

Webflux Securiry Manager

Webflux Securiry Context

Webflux Security Configuration

正如您在这两个中看到的那样,调用了一个外部服务(在 MVC 中使用 RestTemplate 和在 Webflux 中使用 WebClient),以获得所需的授权信息并决定“登录用户”是否通过所需的安全逻辑。

您可以根据需要进行调整。

【讨论】:

我没有使用 MVC(这就是为什么有一个重定向 uri 让我的流程有点模糊)我正在检查 webflux 逻辑,只是为了澄清我的观点,webflux 会帮助我首先发送客户端 ID(以及范围等其他详细信息......)然后使用代码并发出发布请求以获取 jwt 令牌? 在阅读了一些关于 webflux 的内容后,它与我正在构建的内容非常不同,因为我正在构建一个简单的 spring boot rest api,必须应用 webflux 方法意味着我需要更改所有内容,如果我没记错 重定向逻辑应该驻留在客户端代码中,而不是后端。如果您没有/不需要任何 UI,并且它纯粹是后端到后端的流程,那么在这种情况下,您可能需要考虑客户端凭证流程。您仍然可以通过在您的应用程序中引入两个端点来使用授权授权流程。说 /login,它应该重定向到 IDP。另一个端点说 /token 一旦用户成功登录,IDP 将使用代码重定向。在 /token API 中,读取令牌的 url 参数并将其交换为来自 IDP 的 idToken/accesstoken 好的,但正如@Partha 所说,重定向不应包含在后端。在我的回答提供的方法中,您实际上是从外部 API 获取所需的授权信息并在您当前的后台进行管理。如果这可以适应您所需的流程,在我看来,它比任何重定向都更合适 @bleh10,是的,这就是我的意思,你可以调整并做。因为 IDP 不知道也不关心重定向是由浏览器中的 javascript 处理还是由后端处理。 IDP 将在提供的“重定向 url”中附加代码并重定向回来。之后由你来处理。

以上是关于使用 Java Spring Rest Api 执行授权码授予流程的主要内容,如果未能解决你的问题,请参考以下文章

使用 Java Spring Rest Api 执行授权码授予流程

使用 Spring Security Rest 插件保护 Grails Rest Api

Java Spring REST API CORS 不适用于通过 jQuery 和 Chrome 的 DELETE 请求

POST / PUT 上的 Java Spring REST API 状态 400 响应

使用 Spring Security 保护移动 REST Api 足够了吗?

Java Spring Boot将rest api映射到模型[重复]