当前位置: 首页 > 知识库问答 >
问题:

无法在Java Spring Boot/Angular应用程序中获取cookie

姜宏盛
2023-03-14

我正在开发一个Angular11前端应用程序,加上一个Java Spring Boot后端。

我试图用JWT创建一个用Cookie进行身份验证的方法。这样做的灵感来自于

  • JWT刷新令牌流
  • 访问令牌和刷新令牌的最佳实践?如何实现访问和刷新令牌

我的endpoint/authenticate返回一个jwt访问令牌并在cookie中设置一个jwt刷新令牌(仅限于http)。
我的endpoint/refreshtoken从cookie中获取刷新令牌并在生成新的jwt访问令牌和新的jwt刷新令牌之前对其进行验证。
以下是我的authenticationController的代码

    @RestController
    @AllArgsConstructor
    @CrossOrigin(origins = "http://localhost:4200", allowCredentials = "true")
    public class AuthenticationController {
        
            private final AuthenticationManager authenticationManager;
            private final JwtTokenUtil jwtTokenUtil;
            private final UserDetailsServiceImpl userDetailsService;
            private final static String REFRESH_TOKEN_COOKIE = "resfreshtoken";
        
            @PostMapping(value = "/authenticate")
            public ResponseEntity<JwtAuthenticationResponse> createAuthenticationToken(@RequestBody JwtAuthenticationRequest authenticationRequest, HttpServletResponse response) throws Exception {
                try {
                    this.authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(authenticationRequest.getUsername(), authenticationRequest.getPassword()));
                }
                catch (DisabledException e) {
                    throw new Exception("USER_DISABLED", e);
                }
                catch (BadCredentialsException e) {
                    throw new Exception("INVALID_CREDENTIALS", e);
                }
                final UserDetails userDetails = this.userDetailsService.loadUserByUsername(authenticationRequest.getUsername());
                final String token = this.jwtTokenUtil.generateToken(userDetails.getUsername());
                final String refreshToken = this.jwtTokenUtil.generateRefreshToken(new HashMap<>(), userDetails.getUsername());
        
                Cookie cookie = new Cookie(REFRESH_TOKEN_COOKIE, refreshToken);
                cookie.setHttpOnly(true);
                // cookie.setDomain("localhost");
                // cookie.setPath("/");
                response.addCookie(cookie);
        
                return ResponseEntity.ok(new JwtAuthenticationResponse(token));
            }
        
            @GetMapping(value = "/refreshtoken")
            public ResponseEntity<?> refreshToken(@CookieValue(value = REFRESH_TOKEN_COOKIE, required = false) String refreshToken, HttpServletRequest request, HttpServletResponse response) {
                Cookie[] cookies = request.getCookies(); // ALWAYS returns null
                log.debug("refreshToken {}", refreshToken); // ALWAYS null
                try {
                    Claims claims = this.jwtTokenUtil.getAllClaimsFromToken(refreshToken);
                    final String username = claims.get("sub").toString();
                    final String newAccessToken = this.jwtTokenUtil.generateToken(username);
                    final String newRefreshToken = this.jwtTokenUtil.generateRefreshToken(claims, username);
                    CookieUtil.writeCookie(response, REFRESH_TOKEN_COOKIE, newRefreshToken);
        
                    return ResponseEntity.ok(new JwtAuthenticationResponse(newAccessToken));
                }
                catch (SignatureException | MalformedJwtException | UnsupportedJwtException | IllegalArgumentException ex) {
                    throw new BadCredentialsException("INVALID_CREDENTIALS", ex);
                }
                catch (ExpiredJwtException e) {
                    // user should re-login
                }
    
                  return new ResponseEntity<>("Something went wrong", HttpStatus.BAD_REQUEST);
                }
        }

在Angular前端,下面是我添加到/refreshToken Http请求中的选项(WithCredentials=true)

refreshToken(): Observable<AuthenticationResponse> {
        return this.http.get<AuthenticationResponse>(this.apiUrl + 'refreshtoken', { withCredentials: true }).pipe(
            tap(response => LocalStorageUtils.save(LocalStorageKey.JWT_ACCESS_TOKEN_KEY, response.jwtAccessToken))
        );
    }

如果有人能帮忙或对哪里出了问题有个想法,我将不胜感激!如果需要,我可以提供更多关于我的代码的细节。

共有1个答案

凌长恨
2023-03-14

您需要将with Credentials:true添加到Httpoptions中,并将其与HttpClient一起传递给每个请求。您还可以使用HttpClient和拦截器对其进行全局配置。

 类似资料:
  • 我已经在谷歌云功能中构建了API。当我试图直接获取API时,会出现CORS错误。虽然我添加了,但失败了。 来自“http://localhost:3000”的“https://xxxxxxxx.com”已被CORS策略阻止:对飞行前请求的响应未通过访问控制检查:请求的资源上没有“access-control-allog-origin”标头。如果一个不透明的响应满足您的需要,请将请求的模式设置为“n

  • 问题内容: 您能否解释一下如何在我的子类中获取实例?可能吗?我已尝试按照以下代码片段的方式进行操作,但它似乎不起作用- 未设置: web.xml: 问题是我需要从中获取上下文参数。如果有其他方法,请给我一个提示,我将不胜感激。 我了解注记可能并非为此目的。实际上,我不需要自己。如果只有我可以从web.xml中获取上下文参数,我将非常高兴。 这是我真正需要的一个例子: 谢谢。 问题答案: 从Jers

  • 我正在尝试获取postgresql表的列名。我尝试过使用information_模式,但在我的javamvc项目中不起作用。我该怎么办? 这实际上是我关于StackOverflow的第一个问题,如果我的问题很难理解,我很抱歉。非常感谢。

  • 我正在处理使用通知侦听器服务类从通知中读取数据的应用程序。我已完成文本部分,但无法存储通知中收到的图像。 我想存储在WhatsApp应用程序中从通知中收到的图像。我已经尝试了堆栈溢出的所有解决方案,但没有得到任何解决方案。我已经尝试了<代码>通知。EXTRA_PICTURE但它总是返回null。 我见过许多应用程序这样做,但看起来我错过了一些东西。 因此,如果有人能以任何方式提供帮助,我们将不胜感

  • 如果我单击“继续”链接并打开http://ip:4200然后它将再次打开KeyClope登录页面。(在此之后,它不会给我任何错误,并成功地从上面提到的openid配置url获取数据)我如何解决这个问题?从angular应用程序到具有自签名证书的服务的HTTP调用是否与此有关?请帮帮我。谢谢