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 无状态会话的主要内容,如果未能解决你的问题,请参考以下文章