package com.jsl.oa.aspect;
import com.jsl.oa.common.constant.BusinessConstants;
import com.jsl.oa.utils.ErrorCode;
import com.jsl.oa.utils.ResultUtil;
import com.jsl.oa.utils.redis.TokenRedisUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.Objects;
/**
*
用户控制器切面
*
* 用于用户控制器的切面
*
* @author xiao_lfeng
* @version v1.1.0
* @since v1.0.0
*/
@Slf4j
@Aspect
@Component
@RequiredArgsConstructor
public class AuthControllerAspect {
private final TokenRedisUtil tokenRedisUtil;
/**
* 用户控制器切面
*
* 用于用户控制器的切面
*
* @param pjp ProceedingJoinPoint对象
* @return {@link Object}
* @throws Throwable 异常
* @since v1.0.0
*/
@Around("execution(* com.jsl.oa.controllers.*.*(..)) && !execution(* com.jsl.oa.controllers.IndexController.*(..))")
public Object controllerAround(ProceedingJoinPoint pjp) throws Throwable {
// 获取HttpServletRequest对象
HttpServletRequest request =
((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes()))
.getRequest();
// 时间戳检查
if (checkTimestamp(request)) {
// TODO: 2023/12/21 0001 后期固定业务(如:日志处理)
return pjp.proceed();
} else {
return ResultUtil.error(ErrorCode.TIMESTAMP_ERROR);
}
}
/**
* Token检查切面
*
* 用于检查Token是否有效
*
* @param pjp ProceedingJoinPoint对象
* @return {@link Object}
* @throws Throwable 异常
*/
@Around("execution(* com.jsl.oa.controllers.*.*(..)) "
+ "&& !execution(* com.jsl.oa.controllers.AuthController.authSendEmailCode(..))"
+ "&& !execution(* com.jsl.oa.controllers.AuthController.authLoginByEmail(..))"
+ "&& !execution(* com.jsl.oa.controllers.AuthController.authForgetPassword(..))"
+ "&& !execution(* com.jsl.oa.controllers.AuthController.authLogin(..))"
+ "&& !execution(* com.jsl.oa.controllers.AuthController.authRegister(..)) "
+ "&& !execution(* com.jsl.oa.controllers.IndexController.*(..)) "
+ "&& !execution(* com.jsl.oa.controllers.CustomController.*(..)) "
+ "&& !execution(* com.jsl.oa.controllers.InfoController.infoGetHeaderImage(..)) "
+ "&& !execution(* com.jsl.oa.controllers.InfoController.infoGetHeaderUser(..))"
+ "&& !execution(* com.jsl.oa.controllers.ProjectController.*(..))"
+ "&& !execution(* com.jsl.oa.controllers.TagController.*(..))")
public Object tokenControllerAround(ProceedingJoinPoint pjp) throws Throwable {
// 获取 HttpServletRequest 对象
HttpServletRequest request =
((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes()))
.getRequest();
// 检查 Token 是否有效
String token = request.getHeader("Authorization");
if (token != null && !token.isEmpty()) {
// 获取 Redis 检查 Token 是否存在
String finalToken = token.replace("Bearer ", "");
for (String it : tokenRedisUtil.getList(BusinessConstants.BUSINESS_LOGIN)) {
if (it.equals(finalToken)) {
return pjp.proceed();
}
}
}
return ResultUtil.error(ErrorCode.TOKEN_NOT_EXIST);
}
/**
* 时间戳检查
*
* 用于检查时间戳是否合法,合法时间范围正负5秒
*
* @param request HttpServletRequest对象
* @return {@link Boolean}
* @since v1.0.0
*/
private @NotNull Boolean checkTimestamp(@NotNull HttpServletRequest request) {
// 获取请求头中的时间戳
String getTimestamp = request.getHeader("Timestamp");
log.info("\t> 获取到的时间戳为 {} | 当前时间戳 {}", getTimestamp, System.currentTimeMillis());
// 判断是否为空
if (getTimestamp == null || getTimestamp.isEmpty()) {
return false;
} else {
if (getTimestamp.length() == 10) {
getTimestamp += "000";
}
}
// 获取当前时间戳
long nowTimestamp = System.currentTimeMillis();
// 时间误差允许前后五秒钟
return nowTimestamp - Long.parseLong(getTimestamp) <= 10000
&& nowTimestamp - Long.parseLong(getTimestamp) >= -10000;
}
}