gpt4 book ai didi

java - JWT认证: How to implement logout?

转载 作者:塔克拉玛干 更新时间:2023-11-03 04:02:22 24 4
gpt4 key购买 nike

我为我的 Spring Boot 应用程序实现了 JWT 身份验证。总的来说,它是这样工作的:

  1. 客户端将用户名、密码发送到登录端点。
  2. 服务器检查提供的凭据是否有效。
  3. 如果不是,它将返回一个错误
  4. 如果是,它会返回一个 token ,该 token 实际上包括
  5. 客户端在以后的每个请求中发送该 token

问题是,我们应该如何实现注销?

import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import java.util.Date;

class TokenAuthenticationService {
static final long EXPIRATIONTIME = 864_000_000; // 10 days
static final String SECRET = "ThisIsASecret";
static final String TOKEN_PREFIX = "Bearer";
static final String HEADER_STRING = "Authorization";

static void addAuthentication(HttpServletResponse res, String username) {
String JWT = Jwts
.builder()
.setSubject(username)
.setExpiration(
new Date(System.currentTimeMillis() + EXPIRATIONTIME))
.signWith(SignatureAlgorithm.HS512, SECRET).compact();
res.addHeader(HEADER_STRING, TOKEN_PREFIX + " " + JWT);
}

static Authentication getAuthentication(HttpServletRequest request, UserDetailsService customUserDetailsService) {
String token = request.getHeader(HEADER_STRING);
if (token != null) {
// parse the token.
Claims claims = Jwts.parser().setSigningKey(SECRET)
.parseClaimsJws(token.replace(TOKEN_PREFIX, "")).getBody();
String userName = claims.getSubject();
Date expirationTime = claims.getExpiration();
if (expirationTime.compareTo(new Date()) < 0) {
return null;
}
UserDetails user = customUserDetailsService.loadUserByUsername(userName);
return user != null ? new UsernamePasswordAuthenticationToken(user.getUsername(),
user.getPassword(), user.getAuthorities()) : null;
}
return null;
}
}

addAuthenticationJWTLoginFilter 类用来在登录时发送验证码,'getAuthenticationJWTAuthenticationFilter 用来过滤所有对端点的请求。

此处的最佳做法是什么?

最佳答案

我认为这里没有最佳实践。我想这取决于您正在构建的应用程序及其要求。

JWT 的好处是它们是无状态的。您不需要查询数据库来验证 token 。当您希望减少数据库的负载时这很好,但当您希望使现有的未过期 token 无效时则不好。

可能的解决方案:

  • 将 JWT 存储在数据库中。您可以检查哪些 token 有效,哪些 token 已撤销,但我认为这完全违背了使用 JWT 的目的。
  • 从客户端删除 token 。这将阻止客户端发出经过身份验证的请求,但如果 token 仍然有效并且其他人可以访问它,则仍可以使用 token 。这引出了我的下一个观点。
  • token 生命周期短。让 token 快速过期。根据应用程序,可能需要几分钟或半小时。当客户端删除其 token 时,有很短的时间窗口仍然可以使用它。从客户端删除 token 并缩短 token 生命周期不需要对后端进行重大修改。但较短的 token 生命周期意味着用户会因为 token 已过期而不断注销。
  • 轮换代币。也许引入刷新 token 的概念。当用户登录时,为他们提供 JWT 和刷新 token 。将刷新 token 存储在数据库中。对于经过身份验证的请求,客户端可以使用 JWT,但是当 token 过期(或即将过期)时,让客户端使用刷新 token 发出请求以换取新的 JWT。这样,您只需在用户登录或请求新的 JWT 时访问数据库。当用户注销时,您需要使存储的刷新 token 失效。否则,即使用户已注销,监听连接的人仍然可以获得新的 JWT。
  • 创建 JWT 黑名单。根据到期时间,当客户端删除其 token 时,它可能在一段时间内仍然有效。如果 token 生命周期很短,这可能不是问题,但如果您仍然希望 token 立即失效,您可以创建一个 token 黑名单。当后端收到注销请求时,从请求中取出 JWT 并将其存储在内存数据库中。对于每个经过身份验证的请求,您需要检查内存数据库以查看 token 是否已失效。为了保持较小的搜索空间,您可以从黑名单中删除已经过期的 token 。

关于java - JWT认证: How to implement logout?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43569723/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com