@@ -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.utils.JwtUtil ;
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.web.Result ;
import lombok.RequiredArgsConstructor ;
@@ -27,145 +28,195 @@ import java.util.concurrent.TimeUnit;
@Slf4j
public class AuthServiceImpl implements AuthService {
private final JwtUtil jwtUtil ;
private final JwtUtil jwtUtil ;
private final UserLoginRequestParamVerifyContext userLoginRequestParamVerifyContext ;
private final UserLoginRequestParamVerifyContext userLoginRequestParamVerifyContext ;
private final UserClient userClient ;
private final UserClient userClient ;
private final StringRedisTemplate stringRedisTemplate ;
private final StringRedisTemplate stringRedisTemplate ;
private final JwtPropertiesConfiguration jwtPropertiesConfiguration ;
private final JwtPropertiesConfiguration jwtPropertiesConfiguration ;
@Override
public UserLoginResponseDTO userLogin ( UserLoginRequestDTO requestParam ) {
log . info ( " 用户登录请求: userAccount={} " , requestParam . getUserAccount ( ) ) ;
@Override
public UserLoginResponseDTO userLogin ( UserLoginRequestDTO requestParam ) {
log . info ( " 用户登录请求: userAccount={} " , requestParam . getUserAccount ( ) ) ;
// 1.校验
userLoginRequestParamVerifyContext . handler ( ChainMarkEnums . USER_LOGIN_REQ_PARAM_VERIFY . getMarkName ( ) ,
requestParam ) ;
// 1.校验
userLoginRequestParamVerifyContext . handler ( ChainMarkEnums . USER_LOGIN_REQ_PARAM_VERIFY . getMarkName ( ) ,
requestParam ) ;
// 如果调用user-service失败, 那么就说明是系统内部错误
log . info ( " 正在调用user-service查询用户信息... " ) ;
Result < UserAuthRespDTO > userResp = userClient . getUserByUserName ( requestParam . getUserAccount ( ) ) ;
// 如果调用user-service失败, 那么就说明是系统内部错误
log . info ( " 正在调用user-service查询用户信息... " ) ;
Result < UserAuthRespDTO > userResp = userClient . getUserByUserName ( requestParam . getUserAccount ( ) ) ;
if ( userResp . isFail ( ) ) {
log . error ( " 调用user-service返回失败: {} " , userResp . getMessage ( ) ) ;
throw new ServiceException ( ErrorCode . SYSTEM_ERROR ) ;
}
if ( userResp . isFail ( ) ) {
log . error ( " 调用user-service返回失败: {} " , userResp . getMessage ( ) ) ;
throw new ServiceException ( ErrorCode . SYSTEM_ERROR ) ;
}
UserAuthRespDTO user = userResp . getData ( ) ;
if ( user = = null ) {
log . warn ( " 用户不存在: {} " , requestParam . getUserAccount ( ) ) ;
throw new ServiceException ( " 用户不存在或密码错误 " , ErrorCode . NOT_LOGIN_ERROR ) ;
}
UserAuthRespDTO user = userResp . getData ( ) ;
if ( user = = null ) {
log . warn ( " 用户不存在: {} " , requestParam . getUserAccount ( ) ) ;
throw new ServiceException ( " 用户不存在或密码错误 " , ErrorCode . NOT_LOGIN_ERROR ) ;
}
if ( ! BCrypt . checkpw ( requestParam . getUserPassword ( ) , user . getUserPassword ( ) ) ) {
log . warn ( " 密码错误: {} " , requestParam . getUserAccount ( ) ) ;
throw new ServiceException ( " 用户不存在或密码错误 " , ErrorCode . NOT_LOGIN_ERROR ) ;
}
if ( ! BCrypt . checkpw ( requestParam . getUserPassword ( ) , user . getUserPassword ( ) ) ) {
log . warn ( " 密码错误: {} " , requestParam . getUserAccount ( ) ) ;
throw new ServiceException ( " 用户不存在或密码错误 " , ErrorCode . NOT_LOGIN_ERROR ) ;
}
// 生成 JWT
log . info ( " 正在生成JWT token... " ) ;
String accessToken = jwtUtil . generateAccessToken ( user ) ;
String refreshToken = jwtUtil . generateRefreshToken ( user . getId ( ) ) ;
// 生成 JWT
log . info ( " 正在生成JWT token... " ) ;
String accessToken = jwtUtil . generateAccessToken ( user ) ;
String refreshToken = jwtUtil . generateRefreshToken ( user . getId ( ) ) ;
UserLoginResponseDTO resp = new UserLoginResponseDTO ( ) ;
resp . setId ( user . getId ( ) ) ;
resp . setUserAccount ( user . getUserAccount ( ) ) ;
resp . setAccessToken ( accessToken ) ;
resp . setRefreshToken ( refreshToken ) ;
resp . setAccessTokenExpireTime ( jwtPropertiesConfiguration . getAccessExpire ( ) ) ;
resp . setRefreshTokenExpireTime ( jwtPropertiesConfiguration . getRefreshExpire ( ) ) ;
// refresh token存入到REDIS里面
stringRedisTemplate . opsForValue ( )
. set ( String . format ( RedisKeyConstants . REFRESH_TOKEN_KEY_PREFIX , user . getId ( ) ) , refreshToken ,
jwtPropertiesConfiguration . getRefreshExpire ( ) , TimeUnit . MILLISECONDS ) ;
UserLoginResponseDTO resp = new UserLoginResponseDTO ( ) ;
resp . setId ( user . getId ( ) ) ;
resp . setUserAccount ( user . getUserAccount ( ) ) ;
resp . setAccessToken ( accessToken ) ;
resp . setRefreshToken ( refreshToken ) ;
resp . setAccessTokenExpireTime ( jwtPropertiesConfiguration . getAccessExpire ( ) ) ;
resp . setRefreshTokenExpireTime ( jwtPropertiesConfiguration . getRefreshExpire ( ) ) ;
// refresh token存入到REDIS里面
stringRedisTemplate . opsForValue ( )
. set ( String . format ( RedisKeyConstants . REFRESH_TOKEN_KEY_PREFIX , user . getId ( ) ) , refreshToken ,
jwtPropertiesConfiguration . getRefreshExpire ( ) , TimeUnit . MILLISECONDS ) ;
log . info ( " 用户登录成功: userId={}, userAccount={} " , user . getId ( ) , user . getUserAccount ( ) ) ;
return resp ;
}
log . info ( " 用户登录成功: userId={}, userAccount={} " , user . getId ( ) , user . getUserAccount ( ) ) ;
return resp ;
}
/**
* 更新access token, 使用refresh token
* @param refreshToken
* @retur n
*/
@Override
public UserLoginResponseDTO refreshToken ( String refreshToken ) {
UserLoginResponseDTO userLoginResponseDTO = new UserLoginResponseDTO ( ) ;
if ( ! jwtUtil . isTokenValid ( refreshToken ) ) {
throw new ServiceException ( " R efresh Token 已过期 " ) ;
}
/**
* 更新access token, 使用refresh token
*
* @param refreshToke n
* @return
*/
@Override
public UserLoginResponseDTO refreshToken ( String refreshToken ) {
UserLoginResponseDTO userLoginResponseDTO = new UserLoginResponseDTO ( ) ;
if ( ! jwtUtil . isTokenValid ( r efreshToken) ) {
throw new ServiceException ( " Refresh Token 已过期 " ) ;
}
Long userId = Long . valueOf ( jwtUtil . parseClaims ( refreshToken ) . getSubject ( ) ) ;
Long userId = Long . valueOf ( jwtUtil . parseClaims ( refreshToken ) . getSubject ( ) ) ;
String cacheKey = String . format ( RedisKeyConstants . REFRESH_TOKEN_KEY_PREFIX , userId ) ;
String cacheValue = stringRedisTemplate . opsForValue ( ) . get ( cacheKey ) ;
String cacheKey = String . format ( RedisKeyConstants . REFRESH_TOKEN_KEY_PREFIX , userId ) ;
String cacheValue = stringRedisTemplate . opsForValue ( ) . get ( cacheKey ) ;
if ( cacheValue = = null | | ! cacheValue . equals ( refreshToken ) ) {
throw new ServiceException ( " Refresh Token 已失效 " ) ;
}
if ( cacheValue = = null | | ! cacheValue . equals ( refreshToken ) ) {
throw new ServiceException ( " Refresh Token 已失效 " ) ;
}
// 再次签发新的 Access Token
// 此处你需要查用户,拿 userName, role
Result < UserAuthRespDTO > userResult = userClient . getUserById ( String . valueOf ( userId ) ) ;
if ( userResult . isFail ( ) ) {
log . error ( " 通过id查找用户失败:{} " , userResult . getMessage ( ) ) ;
throw new ServiceException ( ErrorCode . SYSTEM_ERROR ) ;
}
UserAuthRespDTO user = userResult . getData ( ) ;
String newAccessToken = jwtUtil . generateAccessToken ( user ) ;
// 再次签发新的 Access Token
// 此处你需要查用户,拿 userName, role
Result < UserAuthRespDTO > userResult = userClient . getUserById ( String . valueOf ( userId ) ) ;
if ( userResult . isFail ( ) ) {
log . error ( " 通过id查找用户失败:{} " , userResult . getMessage ( ) ) ;
throw new ServiceException ( ErrorCode . SYSTEM_ERROR ) ;
}
UserAuthRespDTO user = userResult . getData ( ) ;
String newAccessToken = jwtUtil . generateAccessToken ( user ) ;
// 设置refresh token和access token
userLoginResponseDTO . setRefreshToken ( refreshToken ) ;
userLoginResponseDTO . setAccessToken ( newAccessToken ) ;
userLoginResponseDTO . setAccessTokenExpireTime ( jwtPropertiesConfiguration . getAccessExpire ( ) ) ;
userLoginResponseDTO . setRefreshTokenExpireTime ( jwtPropertiesConfiguration . getRefreshExpire ( ) ) ;
return userLoginResponseDTO ;
}
// 设置refresh token和access token
userLoginResponseDTO . setRefreshToken ( refreshToken ) ;
userLoginResponseDTO . setAccessToken ( newAccessToken ) ;
userLoginResponseDTO . setAccessTokenExpireTime ( jwtPropertiesConfiguration . getAccessExpire ( ) ) ;
userLoginResponseDTO . setRefreshTokenExpireTime ( jwtPropertiesConfiguration . getRefreshExpire ( ) ) ;
return userLoginResponseDTO ;
}
/**
* 验证token的有效性
* @param accessToken 访问令牌
* @return token是否有效
*/
@Override
public Boolean validateToken ( String accessToken ) {
try {
// 1. 检查token格式
if ( accessToken = = null | | accessToken . trim ( ) . isEmpty ( ) ) {
log . warn ( " A ccess t oken is null or e mpty" ) ;
return false ;
}
/**
* 验证token的有效性
*
* @param accessToken 访问令牌
* @return token是否有效
*/
@Override
public Boolean validateToken ( String accessToken ) {
try {
// 1. 检查token格式
if ( a ccessT oken = = null | | accessToken . trim ( ) . isE mpty( ) ) {
log . warn ( " Access token is null or empty " ) ;
return false ;
}
// 2. 验证token签名和过期时间
if ( ! jwtUtil . isTokenValid ( accessToken ) ) {
log . warn ( " Access token is invalid or expired " ) ;
return false ;
}
// 2. 验证token签名和过期时间
if ( ! jwtUtil . isTokenValid ( accessToken ) ) {
log . warn ( " Access token is invalid or expired " ) ;
return false ;
}
// 3. 解析token获取用户信息
String userId = jwtUtil . parseClaims ( accessToken ) . getSubject ( ) ;
if ( userId = = null ) {
log . warn ( " Access token does not contain valid user id " ) ;
return false ;
}
// 3. 解析token获取用户信息
String userId = jwtUtil . parseClaims ( accessToken ) . getSubject ( ) ;
if ( userId = = null ) {
log . warn ( " Access token does not contain valid user id " ) ;
return false ;
}
// 4. 验证用户是否存在(可选,增加安全性)
Result < UserAuthRespDTO > userResult = userClient . getUserById ( userId ) ;
if ( userResult . isFail ( ) | | userResult . getData ( ) = = null ) {
log . warn ( " User not found for id: {} " , userId ) ;
return false ;
}
// 4. 验证用户是否存在(可选,增加安全性)
Result < UserAuthRespDTO > userResult = userClient . getUserById ( userId ) ;
if ( userResult . isFail ( ) | | userResult . getData ( ) = = null ) {
log . warn ( " User not found for id: {} " , userId ) ;
return false ;
}
log . debug ( " Access token validation successful for user: {} " , userId ) ;
return true ;
} catch ( Exception e ) {
log . error ( " Error validating access token " , e ) ;
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 ( ) ;
}
log . debug ( " Access token validation successful for user: {} " , userId ) ;
return true ;
}
catch ( Exception e ) {
log . error ( " Error validating access token " , e ) ;
return false ;
}
}
}