fix: 修复工作流公共 API 调用问题
- 限制远程文档仅访问公网地址并校验重定向目标 - 统一访问令牌 401/403 与过期执行状态 404 语义 - 校正节点查询参数和工作流状态文档
This commit is contained in:
@@ -25,8 +25,9 @@ public class PublicApiInterceptor implements HandlerInterceptor {
|
||||
String requestURI = request.getRequestURI();
|
||||
String apiKey = request.getHeader("ApiKey");
|
||||
|
||||
if (apiKey == null || apiKey.isEmpty()) {
|
||||
if (apiKey == null || apiKey.isBlank()) {
|
||||
Result<Void> failed = Result.fail(401, "密钥不正确");
|
||||
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
|
||||
ResponseUtil.renderJson(response, failed);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
package tech.easyflow.publicapi.interceptor;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* {@link PublicApiInterceptor} 鉴权响应测试。
|
||||
*/
|
||||
public class PublicApiInterceptorTest {
|
||||
|
||||
/**
|
||||
* 验证缺少访问令牌时返回真实 HTTP 401 和统一错误体。
|
||||
*
|
||||
* @throws Exception 拦截器处理失败时抛出
|
||||
*/
|
||||
@Test
|
||||
public void shouldReturnUnauthorizedWhenApiKeyMissing() throws Exception {
|
||||
StringWriter body = new StringWriter();
|
||||
AtomicInteger status = new AtomicInteger();
|
||||
HttpServletRequest request = proxy(
|
||||
HttpServletRequest.class,
|
||||
(instance, method, args) -> {
|
||||
if ("getRequestURI".equals(method.getName())) {
|
||||
return "/public-api/workflow/runAsync";
|
||||
}
|
||||
if ("getHeader".equals(method.getName())) {
|
||||
return null;
|
||||
}
|
||||
throw new AssertionError(
|
||||
"测试路径不应调用 HttpServletRequest."
|
||||
+ method.getName());
|
||||
});
|
||||
HttpServletResponse response = proxy(
|
||||
HttpServletResponse.class,
|
||||
(instance, method, args) -> {
|
||||
if ("setStatus".equals(method.getName())) {
|
||||
status.set((Integer) args[0]);
|
||||
return null;
|
||||
}
|
||||
if ("setContentType".equals(method.getName())) {
|
||||
return null;
|
||||
}
|
||||
if ("getWriter".equals(method.getName())) {
|
||||
return new PrintWriter(body);
|
||||
}
|
||||
throw new AssertionError(
|
||||
"测试路径不应调用 HttpServletResponse."
|
||||
+ method.getName());
|
||||
});
|
||||
|
||||
boolean allowed = new PublicApiInterceptor()
|
||||
.preHandle(request, response, new Object());
|
||||
|
||||
Assert.assertFalse(allowed);
|
||||
Assert.assertEquals(
|
||||
HttpServletResponse.SC_UNAUTHORIZED,
|
||||
status.get());
|
||||
Assert.assertTrue(body.toString().contains("\"errorCode\":401"));
|
||||
Assert.assertTrue(body.toString().contains("密钥不正确"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建接口代理。
|
||||
*
|
||||
* @param type 接口类型
|
||||
* @param handler 调用处理器
|
||||
* @param <T> 接口类型
|
||||
* @return 代理实例
|
||||
*/
|
||||
private <T> T proxy(
|
||||
Class<T> type,
|
||||
java.lang.reflect.InvocationHandler handler) {
|
||||
return type.cast(Proxy.newProxyInstance(
|
||||
type.getClassLoader(),
|
||||
new Class<?>[]{type},
|
||||
handler));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user