简体   繁体   English

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

[英]Springboot + JWT +OAuth2 + AngularJS Stateless session

I am trying various Java Spring based security implementations as follows我正在尝试各种基于 Java Spring 的安全实现,如下所示

1. JWT Authentication 1. JWT 认证

  • User access /用户访问 /
  • Springboot identifies as protected resource and redirects user to /login Springboot 标识为受保护资源并将用户重定向到 /login
  • User enters credentials and browsers does a POST to /authenticate用户输入凭据,浏览器对 /authenticate 执行 POST
  • Server validates the credentials and generates JWT token.服务器验证凭据并生成 JWT 令牌。 Set into response header and redirects to /设置为响应头并重定向到 /
  • Browser loads /.浏览器加载/。 AngularJS recognizes JWT token in the response header and stores the same in the localStorage AngularJS 识别响应头中的 JWT 令牌并将其存储在 localStorage 中
  • All subsequent calls will have the Bearer token in header (injected through httpInterceptor)所有后续调用都将在标头中包含 Bearer 令牌(通过 httpInterceptor 注入)

Note: Stateless Session注意:无状态会话

2. OAuth2 authentication 2.OAuth2认证

  • User access /用户访问 /
  • Springboot identifies as protected resource and redirects user to /login Springboot 标识为受保护资源并将用户重定向到 /login
  • /login is intercepted by Spring security. /login 被 Spring 安全拦截。 Redirects to Oauth2 authorization server with a generated state and redirect URL back to application使用生成的状态重定向到 Oauth2 授权服务器并将 URL 重定向回应用程序
  • User enters credentials用户输入凭据
  • Oauth server redirects back to application URL "/login?code=xxx&state=yyy" Oauth 服务器重定向回应用程序 URL“/login?code=xxx&state=yyy”
  • /login is intercepted by Spring security. /login 被 Spring 安全拦截。 Recognizes the code and state, generates Cookie and sets in response header.识别代码和状态,生成 Cookie 并在响应头中设置。 Redirects to /重定向到 /
  • Browser loads /.浏览器加载/。 Browser recognizes cookie in the response header and stores the same.浏览器识别响应头中的 cookie 并将其存储。
  • If a call is made to /user, the Principal object is populated with the JWT which I am able to extract as follows如果对 /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();
  • All subsequent calls will have the Cookie in the Request所有后续调用都将在请求中包含 Cookie

Note: A Stateful Session is created in server side to store the session details.注意:在服务器端创建有状态会话来存储会话详细信息。 This required to decrypt the cookie and identify the user这需要解密 cookie 并识别用户

Now I want to implement security using Oauth2+JWT but stateless at same time as follows现在我想使用 Oauth2+JWT 但同时无状态来实现安全性,如下所示

3. OAuth2 + JWT + Stateless 3. OAuth2 + JWT + 无状态

  • User access /用户访问 /
  • Springboot identifies as protected resource and redirects user to /login Springboot 标识为受保护资源并将用户重定向到 /login
  • /login is interecepted by Spring security. /login 被 Spring 安全拦截。 Redirects to Oauth2 authorization server with a generated state and redirect URL back to application使用生成的状态重定向到 Oauth2 授权服务器并将 URL 重定向回应用程序
  • User enters credentials用户输入凭据
  • Oauth server redirects back to application URL "/login?code=xxx&state=yyy" Oauth 服务器重定向回应用程序 URL“/login?code=xxx&state=yyy”
  • /login is intercepted by Spring security. /login 被 Spring 安全拦截。 Recognizes the code and state, extract JWT token by invoking OAuth2AuthenticationDetails.getTokenValue() and set in response header.识别代码和状态,通过调用 OAuth2AuthenticationDetails.getTokenValue() 提取 JWT 令牌并在响应头中设置。 Redirect to /重定向到 /
  • Browser loads /.浏览器加载/。 AngularJS recognizes JWT token in the response header and stores the same in the localStorage AngularJS 识别响应头中的 JWT 令牌并将其存储在 localStorage 中
  • All subsequent calls will have the Bearer token in header (injected through httpInterceptor)所有后续调用都将在标头中包含 Bearer 令牌(通过 httpInterceptor 注入)

Question

I am trying to figure out how to implement the highlighted step above我想弄清楚如何实现上面突出显示的步骤

Just an idea/direction, if I got you right: You can create a GenericFilterBean and add that to the HttpSecurity filter chain.只是一个想法/方向,如果我给你正确:您可以创建一个GenericFilterBean并添加到HttpSecurity过滤器链。

When using JWT, there should be something similar (a filter, which extracts the bearer-token from the header) and then populates an Authentication object for Spring Security.使用 JWT 时,应该有类似的东西(一个过滤器,它从头中提取承载令牌),然后为 Spring Security 填充一个Authentication对象。

So the new filter could grab the token from the request and set the response accordingly.因此,新过滤器可以从请求中获取令牌并相应地设置响应。 You could also handle that in an unprotected (!) callback endpoint like login/callback?... , which than sets the cookie for you.您还可以在不受保护的 (!) 回调端点中处理该问题,例如login/callback?... ,它会为您设置 cookie。

In our application, the server (spring boot) is totally stateless and does not have any oauth nor stateful stuff.在我们的应用程序中,服务器(spring boot)是完全无状态的,没有任何 oauth 或有状态的东西。 Obviously it never redirects anything or has any other views/endpoints than / for AngularJS (and some REST-APIs under /api/... ).显然,它从不重定向任何东西或有任何其他视图/端点,而不是 AngularJS 的/ (以及/api/...下的一些 REST-API)。 Thus, the OAuth-flow is totally handled by AngularJS, which in turn checks the callback from the oauth-server and locally sets the JWT-Token (like in your first approach).因此,OAuth-flow 完全由 AngularJS 处理,AngularJS 反过来检查来自 oauth-server 的回调并在本地设置 JWT-Token(就像你的第一种方法)。 In first versions we also tried to mix up redirects with stateless JWT and stateful sessions etc., but this led to very strange behavior with the logins - the state (logged in or not) was not always clear and in some cases redirects were wrong etc.在第一个版本中,我们还尝试将重定向与无状态 JWT 和有状态会话等混为一谈,但这导致登录时出现非常奇怪的行为 - 状态(已登录或未登录)并不总是清晰的,在某些情况下重定向是错误的等.

This might help you implement your desired solution. 可能会帮助您实施所需的解决方案。

The author proposes that once a user successfully authenticates with Oauth2 providers (Google etc), you send a short-lived token as a URL param to your frontend application and use this short-lived token to exchange it for a longer-lived token.作者建议,一旦用户成功通过 Oauth2 提供商(Google 等)进行身份验证,您将一个短期令牌作为 URL 参数发送到您的前端应用程序,并使用此短期令牌将其交换为长期令牌。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM