feat: 添加getUserInfo接口和修复相关bug
- 添加 /getUserInfo 接口,支持根据accessToken获取用户信息 - 修复 JWT subject 从 userAccount 改为 userId - 修复 Results.failure 方法使用 getErrorMessage() 而非 getMessage() - 移除 UserClient.getUserById 方法中的 public 修饰符 - 代码格式化:统一缩进和代码风格 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -13,6 +13,6 @@ public interface UserClient {
|
|||||||
Result<UserAuthRespDTO> getUserByUserName(@RequestParam("userAccount") String userAccount);
|
Result<UserAuthRespDTO> getUserByUserName(@RequestParam("userAccount") String userAccount);
|
||||||
|
|
||||||
@GetMapping("/inner/get-by-userid")
|
@GetMapping("/inner/get-by-userid")
|
||||||
public Result<UserAuthRespDTO> getUserById(@RequestParam("userId") String userId);
|
Result<UserAuthRespDTO> getUserById(@RequestParam("userId") String userId);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package cn.meowrain.aioj.backend.auth.controller;
|
package cn.meowrain.aioj.backend.auth.controller;
|
||||||
|
|
||||||
import cn.meowrain.aioj.backend.auth.dto.req.UserLoginRequestDTO;
|
import cn.meowrain.aioj.backend.auth.dto.req.UserLoginRequestDTO;
|
||||||
|
import cn.meowrain.aioj.backend.auth.dto.resp.UserAuthRespDTO;
|
||||||
import cn.meowrain.aioj.backend.auth.dto.resp.UserLoginResponseDTO;
|
import cn.meowrain.aioj.backend.auth.dto.resp.UserLoginResponseDTO;
|
||||||
import cn.meowrain.aioj.backend.auth.oauth2.service.OAuth2SessionService;
|
import cn.meowrain.aioj.backend.auth.oauth2.service.OAuth2SessionService;
|
||||||
import cn.meowrain.aioj.backend.auth.service.AuthService;
|
import cn.meowrain.aioj.backend.auth.service.AuthService;
|
||||||
@@ -54,4 +55,16 @@ public class AuthController {
|
|||||||
return Results.success(isValid);
|
return Results.success(isValid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/getUserInfo")
|
||||||
|
public Result<UserAuthRespDTO> getUserInfo(@RequestHeader(value = "Authorization", required = false) String authorization) {
|
||||||
|
String token = null;
|
||||||
|
if(authorization != null && authorization.startsWith("Bearer ")){
|
||||||
|
token = authorization.substring(7);
|
||||||
|
}
|
||||||
|
if(token != null && sessionService.isTokenBlacklisted(token)) {
|
||||||
|
return Results.success(null);
|
||||||
|
}
|
||||||
|
return Results.success(authService.getUserInfo(token));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
package cn.meowrain.aioj.backend.auth.service;
|
package cn.meowrain.aioj.backend.auth.service;
|
||||||
|
|
||||||
import cn.meowrain.aioj.backend.auth.dto.req.UserLoginRequestDTO;
|
import cn.meowrain.aioj.backend.auth.dto.req.UserLoginRequestDTO;
|
||||||
|
import cn.meowrain.aioj.backend.auth.dto.resp.UserAuthRespDTO;
|
||||||
import cn.meowrain.aioj.backend.auth.dto.resp.UserLoginResponseDTO;
|
import cn.meowrain.aioj.backend.auth.dto.resp.UserLoginResponseDTO;
|
||||||
|
import cn.meowrain.aioj.backend.framework.core.web.Result;
|
||||||
|
|
||||||
public interface AuthService {
|
public interface AuthService {
|
||||||
|
|
||||||
@@ -26,4 +28,11 @@ public interface AuthService {
|
|||||||
*/
|
*/
|
||||||
Boolean validateToken(String accessToken);
|
Boolean validateToken(String accessToken);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据accessToken获取用户信息
|
||||||
|
* @param accessToken
|
||||||
|
* @return {@link Result<UserAuthRespDTO>}
|
||||||
|
*/
|
||||||
|
UserAuthRespDTO getUserInfo(String accessToken);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import cn.meowrain.aioj.backend.auth.dto.resp.UserLoginResponseDTO;
|
|||||||
import cn.meowrain.aioj.backend.auth.service.AuthService;
|
import cn.meowrain.aioj.backend.auth.service.AuthService;
|
||||||
import cn.meowrain.aioj.backend.auth.utils.JwtUtil;
|
import cn.meowrain.aioj.backend.auth.utils.JwtUtil;
|
||||||
import cn.meowrain.aioj.backend.framework.core.errorcode.ErrorCode;
|
import cn.meowrain.aioj.backend.framework.core.errorcode.ErrorCode;
|
||||||
|
import cn.meowrain.aioj.backend.framework.core.exception.ClientException;
|
||||||
import cn.meowrain.aioj.backend.framework.core.exception.ServiceException;
|
import cn.meowrain.aioj.backend.framework.core.exception.ServiceException;
|
||||||
import cn.meowrain.aioj.backend.framework.core.web.Result;
|
import cn.meowrain.aioj.backend.framework.core.web.Result;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
@@ -88,6 +89,7 @@ public class AuthServiceImpl implements AuthService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新access token,使用refresh token
|
* 更新access token,使用refresh token
|
||||||
|
*
|
||||||
* @param refreshToken
|
* @param refreshToken
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@@ -127,6 +129,7 @@ public class AuthServiceImpl implements AuthService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 验证token的有效性
|
* 验证token的有效性
|
||||||
|
*
|
||||||
* @param accessToken 访问令牌
|
* @param accessToken 访问令牌
|
||||||
* @return token是否有效
|
* @return token是否有效
|
||||||
*/
|
*/
|
||||||
@@ -161,11 +164,59 @@ public class AuthServiceImpl implements AuthService {
|
|||||||
|
|
||||||
log.debug("Access token validation successful for user: {}", userId);
|
log.debug("Access token validation successful for user: {}", userId);
|
||||||
return true;
|
return true;
|
||||||
}
|
} catch (Exception e) {
|
||||||
catch (Exception e) {
|
|
||||||
log.error("Error validating access token", e);
|
log.error("Error validating access token", e);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UserAuthRespDTO getUserInfo(String accessToken) {
|
||||||
|
|
||||||
|
// 1. 参数校验
|
||||||
|
if (accessToken == null || accessToken.isBlank()) {
|
||||||
|
log.warn("Access token is null or empty");
|
||||||
|
throw new ClientException(ErrorCode.PARAMS_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. token 校验
|
||||||
|
if (!jwtUtil.isTokenValid(accessToken)) {
|
||||||
|
log.warn("Access token is invalid or expired");
|
||||||
|
throw new ClientException(ErrorCode.NOT_LOGIN_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 解析 token
|
||||||
|
String userId;
|
||||||
|
try {
|
||||||
|
userId = jwtUtil.parseClaims(accessToken).getSubject();
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("Failed to parse access token", e);
|
||||||
|
throw new ClientException(ErrorCode.NOT_LOGIN_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userId == null) {
|
||||||
|
throw new ClientException(ErrorCode.NOT_LOGIN_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 查询用户信息(IO 操作)
|
||||||
|
Result<UserAuthRespDTO> userResult;
|
||||||
|
try {
|
||||||
|
userResult = userClient.getUserById(userId);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Failed to call user service", e);
|
||||||
|
throw new ClientException(ErrorCode.SYSTEM_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userResult == null || userResult.isFail()) {
|
||||||
|
throw new ClientException(ErrorCode.SYSTEM_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userResult.getData() == null) {
|
||||||
|
throw new ClientException(ErrorCode.NOT_FOUND_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
return userResult.getData();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ public class JwtUtil {
|
|||||||
claims.put("role", user.getUserRole());
|
claims.put("role", user.getUserRole());
|
||||||
|
|
||||||
return Jwts.builder()
|
return Jwts.builder()
|
||||||
.subject(user.getUserAccount())
|
.subject(String.valueOf(user.getId()))
|
||||||
.issuedAt(new Date(now))
|
.issuedAt(new Date(now))
|
||||||
.expiration(new Date(now + jwtConfig.getAccessExpire()))
|
.expiration(new Date(now + jwtConfig.getAccessExpire()))
|
||||||
.claims(claims)
|
.claims(claims)
|
||||||
|
|||||||
@@ -2,9 +2,15 @@ package cn.meowrain.aioj.backend.framework.core.errorcode;
|
|||||||
|
|
||||||
public enum ErrorCode implements IErrorCode {
|
public enum ErrorCode implements IErrorCode {
|
||||||
|
|
||||||
SUCCESS("0", "ok"), PARAMS_ERROR("40000", "请求参数错误"), NOT_LOGIN_ERROR("40100", "未登录"), NO_AUTH_ERROR("40101", "无权限"),
|
SUCCESS("0", "ok"),
|
||||||
NOT_FOUND_ERROR("40400", "请求数据不存在"), FORBIDDEN_ERROR("40300", "禁止访问"), SYSTEM_ERROR("50000", "系统内部异常"),
|
PARAMS_ERROR("40000", "请求参数错误"),
|
||||||
OPERATION_ERROR("50001", "操作失败"), API_REQUEST_ERROR("50010", "接口调用失败");
|
NOT_LOGIN_ERROR("40100", "未登录"),
|
||||||
|
NO_AUTH_ERROR("40101", "无权限"),
|
||||||
|
NOT_FOUND_ERROR("40400", "请求数据不存在"),
|
||||||
|
FORBIDDEN_ERROR("40300", "禁止访问"),
|
||||||
|
SYSTEM_ERROR("50000", "系统内部异常"),
|
||||||
|
OPERATION_ERROR("50001", "操作失败"),
|
||||||
|
API_REQUEST_ERROR("50010", "接口调用失败");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 状态码
|
* 状态码
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ public final class Results {
|
|||||||
*/
|
*/
|
||||||
public static Result<Void> failure(AbstractException exception) {
|
public static Result<Void> failure(AbstractException exception) {
|
||||||
String errorCode = Optional.ofNullable(exception.getErrorCode()).orElse(ErrorCode.SYSTEM_ERROR.code());
|
String errorCode = Optional.ofNullable(exception.getErrorCode()).orElse(ErrorCode.SYSTEM_ERROR.code());
|
||||||
String errorMessage = Optional.ofNullable(exception.getMessage()).orElse(ErrorCode.SYSTEM_ERROR.message());
|
String errorMessage = Optional.ofNullable(exception.getErrorMessage()).orElse(ErrorCode.SYSTEM_ERROR.message());
|
||||||
|
|
||||||
return new Result<Void>().setCode(errorCode).setMessage(errorMessage);
|
return new Result<Void>().setCode(errorCode).setMessage(errorMessage);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user