fix(sentinel): 脱敏数据访问异常并保留异常上报

(cherry picked from commit 194b2d10a8210e93874ad4d1789cf0a4fa4889bd)
This commit is contained in:
PIGCLOUD committed 2026-11-03 14:49:29 +08:00
1 parent 4471c363cb
commit 3fd14644cd
3 files changed
+63

No files matched your search

+10
View File
@@ -55,5 +55,15 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-jackson2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
@@ -28,6 +28,7 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.context.MessageSourceResolvable;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.dao.DataAccessException;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.security.access.AccessDeniedException;
@@ -108,6 +109,19 @@ public class GlobalBizExceptionHandler {
return R.failed("数据库调用异常,请联系管理员处理");
}
/**
* Spring 包装的数据访问异常,避免向客户端回显 SQL 和数据库结构
* @param exception 数据访问异常
* @return 统一失败响应,不向客户端暴露底层 SQL 细节
*/
@ExceptionHandler(DataAccessException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public R handleDataAccessException(DataAccessException exception) {
log.error("数据库调用异常 ex={}", exception.getMessage(), exception);
Tracer.trace(exception);
return R.failed("数据库调用异常,请联系管理员处理");
}
/**
* Feign 远程调用异常,透传远端 R 响应体
* @param e Feign 调用异常
@@ -0,0 +1,39 @@
package com.pig4cloud.pigx.common.sentinel.handle;
import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphU;
import com.pig4cloud.pigx.common.core.constant.CommonConstants;
import com.pig4cloud.pigx.common.core.util.R;
import org.junit.jupiter.api.Test;
import org.springframework.http.HttpStatus;
import org.springframework.jdbc.BadSqlGrammarException;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.method.annotation.ExceptionHandlerMethodResolver;
import java.lang.reflect.Method;
import java.sql.SQLException;
import static org.assertj.core.api.Assertions.assertThat;
class GlobalBizExceptionHandlerTests {
@Test
void dataAccessExceptionMustNotExposeSql() throws Exception {
String sql = "select password, salt from sys_user where username = 'admin'";
BadSqlGrammarException exception = new BadSqlGrammarException("query", sql, new SQLException("syntax error"));
ExceptionHandlerMethodResolver resolver = new ExceptionHandlerMethodResolver(GlobalBizExceptionHandler.class);
Method method = resolver.resolveMethodByThrowable(exception);
assertThat(method).isNotNull();
try (Entry entry = SphU.entry("dataAccessExceptionMustNotExposeSql")) {
R<?> result = (R<?>) method.invoke(new GlobalBizExceptionHandler(), exception);
assertThat(result.getCode()).isEqualTo(CommonConstants.FAIL);
assertThat(result.getMsg()).isEqualTo("数据库调用异常,请联系管理员处理");
assertThat(result.getData()).isNull();
assertThat(method.getAnnotation(ResponseStatus.class).value()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR);
assertThat(entry.getError()).isSameAs(exception);
}
}
}