登录接口

This commit is contained in:
dww
2026-02-03 16:36:01 +08:00
parent caa699a6cd
commit 3808449d4d
10 changed files with 21 additions and 138 deletions

View File

@@ -6,13 +6,10 @@ import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import static com.bicloud.common.utils.RedisConstants.JWT_BLACKLIST_KEY;
/**
* JWT认证拦截器
*/
@@ -23,9 +20,6 @@ public class JwtAuthInterceptor implements HandlerInterceptor {
@Resource
private JwtUtils jwtUtils;
@Resource
private StringRedisTemplate stringRedisTemplate;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 1. 从请求头获取Token
@@ -47,17 +41,7 @@ public class JwtAuthInterceptor implements HandlerInterceptor {
return false;
}
// 4. 检查Token是否在黑名单中
String blacklistKey = JWT_BLACKLIST_KEY + token;
Boolean isBlacklisted = stringRedisTemplate.hasKey(blacklistKey);
if (Boolean.TRUE.equals(isBlacklisted)) {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setContentType("application/json;charset=UTF-8");
response.getWriter().write("{\"code\":401,\"message\":\"Token已失效请重新登录\"}");
return false;
}
// 5. 解析Token获取用户信息
// 4. 解析Token,获取用户信息
Long userId = jwtUtils.getUserIdFromToken(token);
String username = jwtUtils.getUsernameFromToken(token);
@@ -68,7 +52,7 @@ public class JwtAuthInterceptor implements HandlerInterceptor {
return false;
}
// 6. 将用户信息存入ThreadLocal
// 5. 将用户信息存入ThreadLocal
UserContext.setUserId(userId);
UserContext.setUsername(username);

View File

@@ -36,27 +36,11 @@ public class JwtUtils {
}
/**
* 生成AccessToken
* 生成Token
*/
public String generateAccessToken(Long userId, String username) {
public String generateToken(Long userId, String username) {
Date now = new Date();
Date expiryDate = new Date(now.getTime() + jwtProperties.getAccessTokenExpiration() * 1000);
return Jwts.builder()
.subject(String.valueOf(userId))
.claim("username", username)
.issuedAt(now)
.expiration(expiryDate)
.signWith(secretKey)
.compact();
}
/**
* 生成RefreshToken
*/
public String generateRefreshToken(Long userId, String username) {
Date now = new Date();
Date expiryDate = new Date(now.getTime() + jwtProperties.getRefreshTokenExpiration() * 1000);
Date expiryDate = new Date(now.getTime() + jwtProperties.getTokenExpiration() * 1000);
return Jwts.builder()
.subject(String.valueOf(userId))
@@ -127,24 +111,11 @@ public class JwtUtils {
* 从请求头中提取Token
*/
public String extractToken(HttpServletRequest request) {
String bearerToken = request.getHeader(jwtProperties.getTokenHeader());
if (StringUtils.hasText(bearerToken) && bearerToken.startsWith(jwtProperties.getTokenPrefix())) {
return bearerToken.substring(jwtProperties.getTokenPrefix().length());
String token = request.getHeader(jwtProperties.getTokenHeader());
if (StringUtils.hasText(token)) {
return token;
}
return null;
}
/**
* 获取Token剩余有效时间
*/
public Long getTokenRemainingTime(String token) {
Claims claims = parseToken(token);
if (claims == null) {
return 0L;
}
Date expiration = claims.getExpiration();
long remainingTime = (expiration.getTime() - System.currentTimeMillis()) / 1000;
return Math.max(remainingTime, 0L);
}
}

View File

@@ -18,22 +18,12 @@ public class JwtProperties {
private String secret;
/**
* AccessToken过期时间
* Token过期时间
*/
private Long accessTokenExpiration;
/**
* RefreshToken过期时间
*/
private Long refreshTokenExpiration;
private Long tokenExpiration;
/**
* Token请求头名称
*/
private String tokenHeader;
/**
* Token前缀
*/
private String tokenPrefix;
}

View File

@@ -1,6 +1,8 @@
package com.bicloud.config;
import io.swagger.v3.oas.annotations.enums.SecuritySchemeType;
import io.swagger.v3.oas.annotations.security.SecurityScheme;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;

View File

@@ -30,8 +30,7 @@ public class WebMvcConfig implements WebMvcConfigurer {
// 用户相关放行路径
"/user/code",
"/user/register",
"/user/login",
"/user/refresh-token"
"/user/login"
);
}
}

View File

@@ -58,16 +58,6 @@ public class UserController {
return Result.success(loginVo);
}
/**
* 刷新Token
*/
@PostMapping("/refresh-token")
@Operation(summary = "刷新Token")
public Result<String> refreshToken(@RequestParam("refreshToken") String refreshToken) {
String newAccessToken = userService.refreshToken(refreshToken);
return Result.success(newAccessToken);
}
/**
* 用户登出
*/

View File

@@ -17,15 +17,9 @@ import lombok.NoArgsConstructor;
public class LoginVo {
@Schema(description = "访问令牌")
private String accessToken;
private String token;
@Schema(description = "刷新令牌")
private String refreshToken;
@Schema(description = "令牌类型", example = "Bearer")
private String tokenType;
@Schema(description = "访问令牌过期时间(秒)", example = "7200")
@Schema(description = "令牌过期时间(秒)", example = "86400")
private Long expiresIn;
@Schema(description = "用户ID")

View File

@@ -18,11 +18,6 @@ public interface UserService {
*/
LoginVo login(LoginDto loginDto);
/**
* 刷新Token
*/
String refreshToken(String refreshToken);
/**
* 用户登出
*/

View File

@@ -189,61 +189,21 @@ public class UserServiceImpl implements UserService {
}
// 4. 生成Token
String accessToken = jwtUtils.generateAccessToken(user.getId(), user.getUsername());
String refreshToken = jwtUtils.generateRefreshToken(user.getId(), user.getUsername());
String token = jwtUtils.generateToken(user.getId(), user.getUsername());
// 5. 构建返回结果
return LoginVo.builder()
.accessToken(accessToken)
.refreshToken(refreshToken)
.tokenType("Bearer")
.expiresIn(jwtProperties.getAccessTokenExpiration())
.token(token)
.expiresIn(jwtProperties.getTokenExpiration())
.userId(user.getId())
.username(user.getUsername())
.build();
}
@Override
public String refreshToken(String refreshToken) {
// 1. 验证RefreshToken
if (!jwtUtils.validateToken(refreshToken)) {
throw new BusinessException("RefreshToken无效或已过期");
}
// 2. 检查黑名单
String blacklistKey = JWT_BLACKLIST_KEY + refreshToken;
Boolean isBlacklisted = stringRedisTemplate.hasKey(blacklistKey);
if (Boolean.TRUE.equals(isBlacklisted)) {
throw new BusinessException("Token已失效请重新登录");
}
// 3. 从Token中获取用户信息
Long userId = jwtUtils.getUserIdFromToken(refreshToken);
String username = jwtUtils.getUsernameFromToken(refreshToken);
if (userId == null || username == null) {
throw new BusinessException("Token解析失败");
}
// 4. 生成新的AccessToken
return jwtUtils.generateAccessToken(userId, username);
}
@Override
public void logout(String token) {
// 1. 将Token加入黑名单
String blacklistKey = JWT_BLACKLIST_KEY + token;
Long remainingTime = jwtUtils.getTokenRemainingTime(token);
// 2. 设置黑名单过期时间为Token剩余有效时间
stringRedisTemplate.opsForValue().set(
blacklistKey,
"1",
remainingTime,
TimeUnit.SECONDS
);
log.info("用户登出成功Token已加入黑名单");
// 简化版不使用黑名单由前端删除token即可
log.info("用户登出成功");
}
@Override

View File

@@ -55,7 +55,5 @@ logging:
jwt:
secret: bicloud-jwt-secret-key-2024-spring-boot-application-secure-token-generation
access-token-expiration: 7200
refresh-token-expiration: 604800
token-expiration: 86400
token-header: Authorization
token-prefix: "Bearer "