wip: jwt 刷新token临时提交
This commit is contained in:
@@ -2,9 +2,10 @@ package com.youlai.boot.shared.auth.controller;
|
||||
|
||||
import com.youlai.boot.common.enums.LogModuleEnum;
|
||||
import com.youlai.boot.common.result.Result;
|
||||
import com.youlai.boot.shared.auth.model.RefreshTokenRequest;
|
||||
import com.youlai.boot.shared.auth.service.AuthService;
|
||||
import com.youlai.boot.system.model.dto.CaptchaResult;
|
||||
import com.youlai.boot.system.model.dto.LoginResult;
|
||||
import com.youlai.boot.shared.auth.model.CaptchaResult;
|
||||
import com.youlai.boot.shared.auth.model.LoginResult;
|
||||
import com.youlai.boot.common.annotation.Log;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
@@ -53,4 +54,11 @@ public class AuthController {
|
||||
CaptchaResult captcha = authService.getCaptcha();
|
||||
return Result.success(captcha);
|
||||
}
|
||||
|
||||
@Operation(summary = "刷新token")
|
||||
@PostMapping("/refresh-token")
|
||||
public Result<?> refreshToken(@RequestBody RefreshTokenRequest request) {
|
||||
LoginResult loginResult = authService.refreshToken(request);
|
||||
return Result.success(loginResult);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.youlai.boot.shared.auth.model;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 验证码响应对象
|
||||
*
|
||||
* @author Ray Hao
|
||||
* @since 2023/03/24
|
||||
*/
|
||||
@Schema(description = "验证码响应对象")
|
||||
@Builder
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class CaptchaResult {
|
||||
|
||||
@Schema(description = "验证码ID")
|
||||
private String captchaKey;
|
||||
|
||||
@Schema(description = "验证码图片Base64字符串")
|
||||
private String captchaBase64;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.youlai.boot.shared.auth.model;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description ="登录响应对象")
|
||||
@Data
|
||||
@Builder
|
||||
public class LoginResult {
|
||||
|
||||
@Schema(description = "访问令牌")
|
||||
private String accessToken;
|
||||
|
||||
@Schema(description = "token 类型",example = "Bearer")
|
||||
private String tokenType;
|
||||
|
||||
@Schema(description = "刷新令牌")
|
||||
private String refreshToken;
|
||||
|
||||
@Schema(description = "过期时间(单位:毫秒)")
|
||||
private Long expires;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.youlai.boot.shared.auth.model;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 刷新令牌请求参数
|
||||
*
|
||||
* @author haoxr
|
||||
* @since 2024/11/11
|
||||
*/
|
||||
@Schema(description = "刷新令牌请求参数")
|
||||
@Data
|
||||
public class RefreshTokenRequest {
|
||||
|
||||
@Schema(description = "刷新令牌")
|
||||
@NotBlank(message = "刷新令牌不能为空")
|
||||
private String refreshToken;
|
||||
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
package com.youlai.boot.shared.auth.service;
|
||||
|
||||
import com.youlai.boot.system.model.dto.CaptchaResult;
|
||||
import com.youlai.boot.system.model.dto.LoginResult;
|
||||
import com.youlai.boot.shared.auth.model.CaptchaResult;
|
||||
import com.youlai.boot.shared.auth.model.LoginResult;
|
||||
import com.youlai.boot.shared.auth.model.RefreshTokenRequest;
|
||||
|
||||
/**
|
||||
* 认证服务接口
|
||||
@@ -31,4 +32,12 @@ public interface AuthService {
|
||||
* @return 验证码
|
||||
*/
|
||||
CaptchaResult getCaptcha();
|
||||
|
||||
/**
|
||||
* 刷新令牌
|
||||
*
|
||||
* @param request 刷新令牌请求参数
|
||||
* @return 登录结果
|
||||
*/
|
||||
LoginResult refreshToken(RefreshTokenRequest request);
|
||||
}
|
||||
|
||||
@@ -5,12 +5,19 @@ import cn.hutool.captcha.CaptchaUtil;
|
||||
import cn.hutool.captcha.generator.CodeGenerator;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.jwt.JWT;
|
||||
import cn.hutool.jwt.JWTPayload;
|
||||
import cn.hutool.jwt.JWTUtil;
|
||||
import com.youlai.boot.common.constant.SecurityConstants;
|
||||
import com.youlai.boot.common.exception.BusinessException;
|
||||
import com.youlai.boot.common.result.ResultCode;
|
||||
import com.youlai.boot.config.property.SecurityProperties;
|
||||
import com.youlai.boot.core.security.util.SecurityUtils;
|
||||
import com.youlai.boot.shared.auth.enums.CaptchaTypeEnum;
|
||||
import com.youlai.boot.shared.auth.model.RefreshTokenRequest;
|
||||
import com.youlai.boot.shared.auth.service.AuthService;
|
||||
import com.youlai.boot.system.model.dto.CaptchaResult;
|
||||
import com.youlai.boot.system.model.dto.LoginResult;
|
||||
import com.youlai.boot.shared.auth.model.CaptchaResult;
|
||||
import com.youlai.boot.shared.auth.model.LoginResult;
|
||||
import com.youlai.boot.config.property.CaptchaProperties;
|
||||
import com.youlai.boot.core.security.util.JwtUtils;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@@ -41,6 +48,7 @@ public class AuthServiceImpl implements AuthService {
|
||||
private final CodeGenerator codeGenerator;
|
||||
private final Font captchaFont;
|
||||
private final CaptchaProperties captchaProperties;
|
||||
private final SecurityProperties securityProperties;
|
||||
|
||||
/**
|
||||
* 登录
|
||||
@@ -54,16 +62,18 @@ public class AuthServiceImpl implements AuthService {
|
||||
// 创建认证令牌对象
|
||||
UsernamePasswordAuthenticationToken authenticationToken =
|
||||
new UsernamePasswordAuthenticationToken(username.toLowerCase().trim(), password);
|
||||
// 执行用户认证
|
||||
// 执行用户认证,认证成功返回的Authentication是SysUserDetailsService#loadUserByUsername获取到的的UserDetails
|
||||
Authentication authentication = authenticationManager.authenticate(authenticationToken);
|
||||
// 认证成功后生成JWT令牌
|
||||
String accessToken = JwtUtils.createToken(authentication);
|
||||
String accessToken = JwtUtils.createAccessToken(authentication);
|
||||
String refreshToken = JwtUtils.createRefreshToken(authentication);
|
||||
// 将认证信息存入Security上下文,便于在AOP(如日志记录)中获取当前用户信息
|
||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
// 返回包含JWT令牌的登录结果
|
||||
return LoginResult.builder()
|
||||
.tokenType("Bearer")
|
||||
.accessToken(accessToken)
|
||||
.refreshToken(refreshToken)
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -122,4 +132,36 @@ public class AuthServiceImpl implements AuthService {
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新令牌
|
||||
*
|
||||
* @param request 刷新令牌请求参数
|
||||
* @return 新的访问令牌
|
||||
*/
|
||||
@Override
|
||||
public LoginResult refreshToken(RefreshTokenRequest request) {
|
||||
// 验证刷新令牌
|
||||
|
||||
String refreshToken = request.getRefreshToken();
|
||||
|
||||
JWT jwt = JWTUtil.parseToken(refreshToken);
|
||||
boolean isValidate = jwt.setKey(securityProperties.getJwt().getKey().getBytes()).validate(0);
|
||||
|
||||
if (!isValidate || redisTemplate.hasKey(SecurityConstants.BLACKLIST_TOKEN_PREFIX + jwt.getPayloads().getStr(JWTPayload.JWT_ID))) {
|
||||
throw new BusinessException(ResultCode.TOKEN_INVALID);
|
||||
}
|
||||
|
||||
Authentication authentication = JwtUtils.getAuthentication(jwt.getPayloads());
|
||||
|
||||
// 创建新的访问令牌
|
||||
String newAccessToken = JwtUtils.createAccessToken(authentication);
|
||||
|
||||
// 返回新的访问令牌
|
||||
return LoginResult.builder()
|
||||
.tokenType("Bearer")
|
||||
.accessToken(newAccessToken)
|
||||
.refreshToken(refreshToken) // 保持刷新令牌不变
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ package com.youlai.boot.shared.file.controller;
|
||||
|
||||
import com.youlai.boot.common.result.Result;
|
||||
import com.youlai.boot.shared.file.service.FileService;
|
||||
import com.youlai.boot.system.model.dto.FileInfo;
|
||||
import com.youlai.boot.shared.file.model.FileInfo;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.enums.ParameterIn;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.youlai.boot.shared.file.model;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "文件对象")
|
||||
@Data
|
||||
public class FileInfo {
|
||||
|
||||
@Schema(description = "文件名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "文件URL")
|
||||
private String url;
|
||||
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.youlai.boot.shared.file.service;
|
||||
|
||||
import com.youlai.boot.system.model.dto.FileInfo;
|
||||
import com.youlai.boot.shared.file.model.FileInfo;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
/**
|
||||
|
||||
@@ -9,7 +9,7 @@ import com.aliyun.oss.OSSClientBuilder;
|
||||
import com.aliyun.oss.model.ObjectMetadata;
|
||||
import com.aliyun.oss.model.PutObjectRequest;
|
||||
import com.youlai.boot.shared.file.service.FileService;
|
||||
import com.youlai.boot.system.model.dto.FileInfo;
|
||||
import com.youlai.boot.shared.file.model.FileInfo;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import lombok.Data;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
@@ -6,7 +6,7 @@ import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.youlai.boot.shared.file.service.FileService;
|
||||
import com.youlai.boot.system.model.dto.FileInfo;
|
||||
import com.youlai.boot.shared.file.model.FileInfo;
|
||||
import io.minio.*;
|
||||
import io.minio.errors.*;
|
||||
import io.minio.http.Method;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.youlai.boot.shared.websocket.controller;
|
||||
|
||||
import com.youlai.boot.system.model.dto.ChatMessage;
|
||||
import com.youlai.boot.shared.websocket.model.ChatMessage;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.messaging.handler.annotation.DestinationVariable;
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.youlai.boot.shared.websocket.model;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 系统消息体
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class ChatMessage {
|
||||
|
||||
/**
|
||||
* 发送者
|
||||
*/
|
||||
private String sender;
|
||||
|
||||
/**
|
||||
* 消息内容
|
||||
*/
|
||||
private String content;
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user