package top.baogutang.music.aspect; import com.fasterxml.jackson.core.type.TypeReference; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import top.baogutang.music.annos.Vip; import top.baogutang.music.domain.res.user.UserLoginRes; import top.baogutang.music.enums.UserLevel; import top.baogutang.music.exceptions.LoginException; import top.baogutang.music.exceptions.VipException; import top.baogutang.music.service.IUserService; import top.baogutang.music.utils.CacheUtil; import top.baogutang.music.utils.TokenUtil; import top.baogutang.music.utils.UserLevelThreadLocal; import top.baogutang.music.utils.UserThreadLocal; import javax.annotation.Resource; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import java.lang.reflect.Method; import java.util.Arrays; import java.util.Objects; import static top.baogutang.music.aspect.LoginAspect.AUTHORIZATION; import static top.baogutang.music.constants.CacheKey.KEY_USER_LEVEL_PREFIX; import static top.baogutang.music.constants.CacheKey.KEY_USER_LOGIN_PREFIX; /** * * @description: * * @author: N1KO * @date: 2024/12/13 : 18:36 */ @Slf4j @Aspect @Component public class VipAspect { @Resource private RedisTemplate redisTemplate; @Resource private IUserService userService; @Pointcut("@annotation(top.baogutang.music.annos.Vip)") public void vip() { } @Around("vip()") public Object around(ProceedingJoinPoint point) throws Throwable { HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest(); MethodSignature signature = (MethodSignature) point.getSignature(); Method method = signature.getMethod(); Vip vip = method.getAnnotation(Vip.class); if (vip != null) { Cookie[] cookies = request.getCookies(); if (Objects.isNull(cookies) || cookies.length == 0) { throw new LoginException("请登录后操作"); } Cookie tokenCookie = Arrays.stream(cookies) .filter(cookie -> AUTHORIZATION.equalsIgnoreCase(cookie.getName())) .findFirst() .orElse(null); if (Objects.isNull(tokenCookie) || StringUtils.isBlank(tokenCookie.getValue())) { throw new LoginException("请登录后操作"); } String token = tokenCookie.getValue(); UserLoginRes userLoginRes = TokenUtil.verify(token); Long userId = userLoginRes.getId(); Object val = redisTemplate.opsForValue().get(KEY_USER_LOGIN_PREFIX + userId); if (Objects.isNull(val)) { throw new LoginException("登录已失效"); } if (!token.equals(val.toString())) { throw new LoginException("登录已失效"); } UserThreadLocal.set(userId); String userLevelCacheKey = KEY_USER_LEVEL_PREFIX + userId; UserLevel userLevel = CacheUtil.cacheOrSupply(userLevelCacheKey, null, null, redisTemplate, () -> userService.queryUserLevel(userId), new TypeReference() { }); UserLevelThreadLocal.set(userLevel); if (Objects.equals(UserLevel.NORMAL, userLevel)) { throw new VipException("请升级当前登录用户等级再操作~(详情联系微信:18010816106)"); } } return point.proceed(); } @After("vip()") public void after() { UserLevelThreadLocal.remove(); } }