Springboot + JWT +OAuth2 + AngularJS 无状态会话

Posted

技术标签:

【中文标题】Springboot + JWT +OAuth2 + AngularJS 无状态会话【英文标题】:Springboot + JWT +OAuth2 + AngularJS Stateless session 【发布时间】:2020-04-11 20:15:55 【问题描述】:

我正在尝试各种基于 Java Spring 的安全实现,如下所示

1. JWT 身份验证

用户访问/ Springboot 识别为受保护资源并将用户重定向到 /login 用户输入凭据,浏览器执行 POST 到 /authenticate 服务器验证凭据并生成 JWT 令牌。设置为响应头并重定向到 / 浏览器加载 /. AngularJS 识别响应头中的 JWT 令牌并将其存储在 localStorage 中 所有后续调用都将在标头中包含 Bearer 令牌(通过 httpInterceptor 注入)

注意:无状态会话

2。 OAuth2 身份验证

用户访问/ Springboot 识别为受保护资源并将用户重定向到 /login /login 被 Spring 安全拦截。使用生成的状态重定向到 Oauth2 授权服务器并将 URL 重定向回应用程序 用户输入凭据 Oauth 服务器重定向回应用程序 URL“/login?code=xxx&state=yyy” /login 被 Spring 安全拦截。识别代码和状态,生成 Cookie 并设置在响应头中。重定向到 / 浏览器加载 /。浏览器识别响应标头中的 cookie 并将其存储。 如果调用 /user,Principal 对象将填充 JWT,我可以按如下方式提取该 JWT
@RequestMapping(value= "/user")
public ResponseEntity<Map<String, String>> user(Principal principal) throws Exception 
    OAuth2Authentication obj = (OAuth2Authentication) principal;
    authentication = obj.getUserAuthentication();
    OAuth2AuthenticationDetails oAuth2AuthenticationDetails = (OAuth2AuthenticationDetails) obj.getDetails();
    String jwt = oAuth2AuthenticationDetails.getTokenValue();
所有后续调用都将在请求中包含 Cookie

注意:在服务器端创建一个有状态会话来存储会话详细信息。这需要解密 cookie 并识别用户

现在我想使用 Oauth2+JWT 实现安全性,但同时无状态,如下所示

3。 OAuth2 + JWT + 无状态

用户访问/ Springboot 识别为受保护资源并将用户重定向到 /login /login 被 Spring 安全拦截。使用生成的状态重定向到 Oauth2 授权服务器并将 URL 重定向回应用程序 用户输入凭据 Oauth 服务器重定向回应用程序 URL“/login?code=xxx&state=yyy”
/login 被 Spring 安全拦截。识别代码和状态,通过调用提取 JWT 令牌 OAuth2AuthenticationDetails.getTokenValue() 并在响应中设置 标题。重定向到 /
浏览器加载 /. AngularJS 识别响应头中的 JWT 令牌并将其存储在 localStorage 中 所有后续调用都将在标头中包含 Bearer 令牌(通过 httpInterceptor 注入)

问题

我正在尝试弄清楚如何实现上面突出显示的步骤

【问题讨论】:

编辑 1:这个问题 ***.com/questions/51456479/… 与我正在尝试做的事情相反,即在重定向到 OAuth 服务器时发送参数 您找到解决方案了吗?我也想实现第三个实现。 【参考方案1】:

只是一个想法/方向,如果我没听错的话: 您可以创建一个GenericFilterBean 并将其添加到 HttpSecurity 过滤器链中。

当使用 JWT 时,应该有类似的东西(一个过滤器,它从标头中提取承载令牌),然后为 Spring Security 填充一个 Authentication 对象。

因此新过滤器可以从请求中获取令牌并相应地设置响应。 您还可以在像login/callback?... 这样的未受保护的 (!) 回调端点中处理它,然后为您设置 cookie。

在我们的应用程序中,服务器(spring boot)是完全无状态的,没有任何 oauth 或有状态的东西。显然,它永远不会重定向任何东西或有任何其他视图/端点,而不是 AngularJS 的/(以及/api/... 下的一些 REST-API)。因此,OAuth 流程完全由 AngularJS 处理,AngularJS 反过来检查来自 oauth-server 的回调并在本地设置 JWT-Token(就像在您的第一种方法中一样)。在第一个版本中,我们还尝试将重定向与无状态 JWT 和有状态会话等混为一谈,但这会导致登录出现非常奇怪的行为 - 状态(是否登录)并不总是清晰的,在某些情况下重定向是错误的等.

【讨论】:

【参考方案2】:

This 可能会帮助您实施所需的解决方案。

作者建议,一旦用户成功通过 Oauth2 提供商(Google 等)进行身份验证,您就可以将一个短期令牌作为 URL 参数发送到您的前端应用程序,并使用这个短期令牌将其交换为一个长期存在的令牌令牌。

【讨论】:

以上是关于Springboot + JWT +OAuth2 + AngularJS 无状态会话的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot 2 和 OAuth2/JWT

如何在单元测试SpringBoot中解析JWT令牌

使用 JWT 来保护你的 SpringBoot 应用

Springboot security oauth2 jwt实现权限控制,实现微服务获取当前用户信息

Oauth2 + jwt 和 spring boot

Spring OAuth2RestTemplate 在配置为使用 JWT 时丢失令牌