jeecgboot/JeecgBoot · error · IllegalArgumentException
无法获取请求上下文
Error message
无法获取请求上下文
What it means
Thrown by SignatureCheckAspect.doSignatureValidation() when RequestContextHolder.getRequestAttributes() returns null — the current thread has no servlet request context bound to it. This AOP aspect runs as a @Before advice on methods annotated with @SignatureCheck; if the method is somehow invoked outside of an HTTP request thread (where RequestContextHolder has no attributes), this guard fires.
Source
Thrown at jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/config/sign/aspect/SignatureCheckAspect.java:82
// update-begin---author:sjlei---date:20260115 for: 查找带有@RequestBody注解的参数,解决签名校验时读取请求体为空的问题
Object bodyParam = null;
Object[] args = point.getArgs();
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
for (int i = 0; i < args.length; i++) {
Object arg = args[i];
Annotation[] annotations = parameterAnnotations[i];
boolean hasRequestBodyAnnotation = Arrays.stream(annotations).anyMatch(annotation -> annotation.annotationType().equals(RequestBody.class));
if (hasRequestBodyAnnotation) {
// 捕获携带@RequestBody注解的参数,供签名校验使用
bodyParam = arg;
}
}
// update-end-----author:sjlei---date:20260115 for: 查找带有@RequestBody注解的参数,解决签名校验时读取请求体为空的问题
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (attributes == null) {
log.error("无法获取请求上下文");
throw new IllegalArgumentException("无法获取请求上下文");
}
HttpServletRequest request = attributes.getRequest();
log.info("X-SIGN: {}, X-TIMESTAMP: {}", request.getHeader("X-SIGN"), request.getHeader("X-TIMESTAMP"));
try {
// 直接调用SignAuthInterceptor的验证逻辑
signAuthInterceptor.validateSignature(request, bodyParam);
log.info("AOP签名验证通过");
} catch (IllegalArgumentException e) {
// 使用注解中配置的错误消息,或者保留原始错误消息
String errorMessage = signatureCheck.errorMessage();
log.error("AOP签名验证失败: {}", e.getMessage());
if ("Sign签名校验失败!".equals(errorMessage)) {
// 如果是默认错误消息,使用原始的详细错误信息
throw e;View on GitHub (pinned to 96fb33f5ec)
Solutions
- Ensure @SignatureCheck methods are only invoked within HTTP request threads — do not call them from async/scheduled/background code.
- If the method must be callable from both web and non-web contexts, remove @SignatureCheck and apply signature validation conditionally.
- For async processing that needs request context, use RequestContextHolder.setRequestAttributes(attrs, true) to propagate, or pass the request data explicitly.
- In tests, use MockMvc or set up RequestContextHolder with a MockHttpServletRequest before invoking.
Example fix
// before — @SignatureCheck method called from async context
@Async
public void processData(SignedRequest req) {
myController.signedMethod(req); // triggers aspect, no request context
}
// after — propagate request context or extract validation
@Async
public void processData(SignedRequest req, ServletRequestAttributes attrs) {
RequestContextHolder.setRequestAttributes(attrs, true);
myController.signedMethod(req);
}
// Or: perform signature validation before entering async, not inside it. Defensive patterns
Strategy: validation
Validate before calling
// Before calling a @SignatureCheck method from non-web context:
ServletRequestAttributes attrs = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (attrs == null) {
// do not call the signed method, or set up context first
return;
} Type guard
private static boolean hasRequestContext() {
return RequestContextHolder.getRequestAttributes() != null;
} Try / catch
try {
// call @SignatureCheck method
} catch (IllegalArgumentException e) {
if ("无法获取请求上下文".equals(e.getMessage())) {
log.error("SignatureCheck invoked outside HTTP request thread");
}
throw e;
} Prevention
- Do not invoke @SignatureCheck methods from async, scheduled, or message-listener threads.
- If request context must cross threads, use RequestContextHolder.setRequestAttributes(attrs, true).
- In tests, use MockMvc or manually set RequestContextHolder with MockHttpServletRequest.
When it happens
Trigger: A @SignatureCheck-annotulated method is called from a non-web thread (e.g., @Async method, scheduled Quartz job, message listener, or internal service-to-service call); the RequestContextHolder has not been configured to inherit child threads (RequestContextListener or RequestContextHolder.setInheritableThreadLocal(true) not set); the aspect is accidentally triggered during unit testing without a mock request context.
Common situations: A @SignatureCheck method is called from a background thread or async handler; an integration test invokes the controller method directly without setting up MockHttpServletRequest; the method is invoked from a message-driven bean (RabbitMQ/Kafka listener) that has no HTTP context.
Related errors
- Could not parse date, date format is error
- Sign签名校验失败!
- Sign签名校验失败,请求参数不完整!
- 签名验证失败,请求时效性验证失败!
- Sign签名校验失败!
AI-assisted analysis of jeecgboot/JeecgBoot@96fb33f5ec (2026-08-14).
Data as JSON: /api/errors/c9e0156d384ee475.
Report an issue: GitHub.