47 lines
1.9 KiB
Java
47 lines
1.9 KiB
Java
package com.aida.seller.common.aop;
|
||
|
||
import com.aida.seller.common.annotation.InternalOnly;
|
||
import com.aida.seller.common.constants.CommonConstants;
|
||
import com.aida.seller.common.exception.BusinessException;
|
||
import jakarta.servlet.http.HttpServletRequest;
|
||
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.aspectj.lang.reflect.MethodSignature;
|
||
import org.springframework.stereotype.Component;
|
||
import org.springframework.web.context.request.RequestContextHolder;
|
||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||
|
||
/**
|
||
* AOP 切面:校验 {@link InternalOnly} 标记的方法是否来自内部服务调用。
|
||
* <p>
|
||
* 内部调用(Feign)会携带 {@link CommonConstants#INTERNAL_CALL_HEADER} Header,
|
||
* 外部直接 HTTP 请求则不携带,视为非法访问。
|
||
*/
|
||
@Slf4j
|
||
@Aspect
|
||
@Component
|
||
@RequiredArgsConstructor
|
||
public class InternalOnlyAspect {
|
||
|
||
@Around("@annotation(com.aida.seller.common.annotation.InternalOnly)")
|
||
public Object validateInternalCall(ProceedingJoinPoint joinPoint) throws Throwable {
|
||
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
||
if (attributes == null) {
|
||
throw new BusinessException("禁止外部直接访问此接口");
|
||
}
|
||
|
||
HttpServletRequest request = attributes.getRequest();
|
||
String internalCall = request.getHeader(CommonConstants.INTERNAL_CALL_HEADER);
|
||
if (!CommonConstants.INTERNAL_CALL_VALUE.equals(internalCall)) {
|
||
log.warn("Unauthorized external access attempt to internal-only endpoint: {}",
|
||
((MethodSignature) joinPoint.getSignature()).getMethod().getName());
|
||
throw new BusinessException("禁止外部直接访问此接口");
|
||
}
|
||
|
||
return joinPoint.proceed();
|
||
}
|
||
}
|