java 如何在Sping Boot 中使用Spring Security注销后使jwt令牌无效

vvppvyoh  于 2023-09-29  发布在  Java
关注(0)|答案(2)|浏览(189)

我尝试在Sping Boot 中使用jwt token实现一个示例。它包括注册,登录,刷新令牌和最后注销过程。我在注销过程中遇到问题。
我试图在注销后删除jwt令牌,但我认为使jwt令牌无效的过程是处理此过程的最佳方法。
下面是auth服务的注销方法
下面是注销请求

@Data
@AllArgsConstructor
@NoArgsConstructor
public class LogoutRequest {

    private String token;
}

下面是控制器的注销方法

@PostMapping("/logout")
public ResponseEntity<String> logout(@RequestBody LogoutRequest request) {

    return ResponseEntity.ok(authService.logout(request));
}

下面是getIdFromToken

public Long getIdFromToken(String token){
    return Long.parseLong(extractClaims(token).getId());
}

下面是deleteByUserId

@Override
public int deleteByUserId(Long userId) {

    User user = userService.findById(userId).orElseThrow(() -> new RuntimeException("User not found"));
    return refreshTokenRepository.deleteByUser(user);
}

我怎么能这么做呢?
下面是repo:Link

vql8enpb

vql8enpb1#

答案如下:
这里你已经建立了一个登录,在成功登录时,你在你的服务中创建了你的JWT,并直接向调用客户端分发一个令牌。这在oauth2中被称为implicit flow,并从oauth2 rfc中被弃用,因为它被发现不安全。
您还构建了某种自定义解决方案,其中包含某种称为刷新令牌的东西,它基本上将ID存储在某种存储中。
因此,原则上,您实际构建的是某种包含状态的会话身份验证,但使用JWT完全自定义。
您已经尝试重新发明Spring Security中已经存在的东西,称为FormLogin,它基本上可以做您想要的所有事情,唯一的区别是FormLogin使用cookie(具有httpOnlySecuredsame-site等其他安全功能),但使用JWT。
所以你最终得到的是和FormLogin一样的东西,只是不那么安全。
“注销”一个JWT是不可能的。您只能通过让JWT超时来使其无效。一旦创建了一个JWT,设置了到期日期,然后签名,它就签名了。合同已经写好了。
代码的问题是,当有人向您的应用程序提供JWT时,检查JWT的过滤器只检查标记和过期是否仍然有效。

// Checking the validity and expiration
Jwts.parserBuilder()
    .setSigningKey(getSignInKey())
    .build()
    .parseClaimsJws(authToken);

只要标志和时间戳仍然有效,您的JWT将通过这里:

if (jwt != null && jwtUtils.validateJwtToken(jwt)) {
    // some other code
}

这意味着您永远不会检查令牌是否在您的自定义refreshToken数据库中实际 * 注销 *,因此过滤器永远不会理解任何注销。
所以你需要在这里做一个检查,但请记住,你将在对你的服务的每个请求中,你可能需要做2个数据库调用。一个用于检查令牌是否未注销,另一个用于检查用户是否存在并将其登录。这是每个请求的2个数据库调用,除非你把东西存储在内存中,或者使用缓存等卸载。
底线是,你基本上是在尝试使用JWT构建FormLogin,但不太安全,可能性能也不太好,我强烈建议你不要这样做。

6l7fqoea

6l7fqoea2#

你不能否定一个JWT。
您可以使OAuth2授权服务器(传递令牌的服务器)和OAuth2客户端(令牌传递到的客户端)上的会话无效。
Spring Security客户端实现可以配置为执行以下两种操作:利用所述客户端上的注销后处理程序从所述授权服务器执行注销。
问题是,显然,应用程序配置和使用的流与OAuth2无关,这最终导致了另一个答案中指出的非常不安全和低效的事情。你应该把所有这些都扔掉,选择:

  • formLogin(具有会话和CSRF保护),如果您不需要外部化身份验证(与信息系统的其余部分进行SSO)或安全的微服务间调用
  • 正确的OAuth2,否则(服务器上有机密客户端)

相关问题