首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在spring应用程序中使用oauth2ResourceServer JWT实现RESTFUL注销API的逻辑

在spring应用程序中使用oauth2ResourceServer JWT实现RESTFUL注销API的逻辑
EN

Stack Overflow用户
提问于 2022-10-28 01:26:59
回答 1查看 34关注 0票数 1

我遇到的问题是在用户通过身份验证后--意思是用户已经登录了,我从客户端了解到要注销一个用户,我从本地存储中删除令牌,但问题是如何使令牌无效或从服务器端注销。

我最初的方法是让logout API许可全部在我的SecurityFilterChain中,但是当我试图在用户登录后从SecurityContextHolder抓取经过身份验证的用户时,我就得到了anonymousUser

我的第二种/当前方法是授权LOGOUT API,这意味着访问API,必须在标头中传递令牌。然后,我可以设置SecurityContextHolder.getContext().setAuthentication(authentication == false);clearContext()。通过这种方法,我可以获得登录用户,但我的问题是:

  1. 是实现注销的正确逻辑吗?据我所知,令牌不能失效,因为它是STATELESS。但有办法绕过这件事吗?因为即使在SecurityContextHolder中将身份验证设置为false并在尝试访问经过身份验证的API (即CRUD operations )时清除安全上下文SecurityContextHolder.clearContext();,我仍然能够使用令牌.

以下是我在RestController类中的登录和注销方法

注销

代码语言:javascript
复制
@PostMapping(path = "/logout", headers = "Authorization")
@ResponseStatus(OK)
public ResponseEntity<?> logout() {
        LOGGER.info("Trying to Logout ");

        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String username = authentication.getName();
        LOGGER.info("Username {} ", username);
        authentication.setAuthenticated(false);
        SecurityContextHolder.getContext().setAuthentication(authentication);
        SecurityContextHolder.clearContext();

        return ResponseEntity.ok().body("Successfully logged out");
    }

登录

代码语言:javascript
复制
@PostMapping(path = "/login", consumes = "application/json", produces = "application/json")
@ResponseStatus(OK)
public ResponseEntity<?> login(@Valid @RequestBody UserDTO userDTO) {

        Authentication authentication;
        LOGGER.info("Authenticating {}", userDTO.getUsername());

        var authenticationToken = confirmUser(userDTO); // returns a UsernamePasswordAuthenticationToken
        try {
            authentication = authenticationManager.authenticate(authenticationToken); // Authenticate user password token
            SecurityContextHolder.getContext().setAuthentication(authentication); // Set the security context to the logged user
        } catch (AuthenticationException e) {
            LOGGER.error("Stack trace {}", e.getMessage());
            SecurityContextHolder.getContext().setAuthentication(null);
            throw new InvalidPasswordException("Wrong username or password");
        }

        LOGGER.info("{} has signed in", userDTO.getUsername());
        return ResponseEntity.ok()
                .header( AUTHORIZATION, tokenService.generateToken(authentication) )
                .build();
    }
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-10-28 20:26:39

我可能会推荐一种不同的方法,但让我们从你的问题开始。

到期访问令牌

若要使资源服务器令牌过期,您需要添加某种状态。

这通常是以某种有效令牌列表的形式出现的。如果令牌不在列表中,则令牌无效。

实现这一目标的一个常见方法是依赖授权服务器。许多授权服务器都附带了一个端点,您可以点击该端点来查看令牌是否仍然有效。

以不同的方式建模

尽管如此,如果您应该以不同的方式来考虑访问令牌,这可能是值得考虑的。访问令牌不表示用户经过身份验证的会话。它表示授予客户端代表用户操作的权限的用户。

因此,在用户注销后,客户端拥有一个有效的访问令牌仍然很有意义,这样用户就不必每次登录时都重新授权客户机。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74229764

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档