feat(forgery-detection): 添加图片篡改检测接口认证和优化测试

- 在ForgeryDetectionController中添加@EbAuthentication注解支持腾讯云认证
- 导入ApiConstants常量用于认证配置
- 重构测试类TestForgeryDetection,使用base64方式传输图片数据
- 添加HTTP客户端超时配置(连接和读取超时均为30秒)
- 实现图片下载转base64功能,避免文件IO问题
- 添加热力图结果截断显示逻辑,防止大量数据输出
- 新增callBaiduApiRaw方法使用原生HttpURLConnection发送请求
- 更新测试用例从URL模式改为base64模式并添加访问间隔控制
This commit is contained in:
zhengli 2026-05-25 20:44:22 +08:00
parent 4cfa182013
commit 8ea4e1225e
2 changed files with 90 additions and 34 deletions

View File

@ -3,7 +3,9 @@ package com.heyu.api.controller.doc;
import com.heyu.api.baidu.handle.doc.BForgeryDetectionHandle; import com.heyu.api.baidu.handle.doc.BForgeryDetectionHandle;
import com.heyu.api.baidu.request.doc.BForgeryDetectionRequest; import com.heyu.api.baidu.request.doc.BForgeryDetectionRequest;
import com.heyu.api.baidu.response.doc.BForgeryDetectionResp; import com.heyu.api.baidu.response.doc.BForgeryDetectionResp;
import com.heyu.api.data.annotation.EbAuthentication;
import com.heyu.api.data.annotation.NotIntercept; import com.heyu.api.data.annotation.NotIntercept;
import com.heyu.api.data.constants.ApiConstants;
import com.heyu.api.data.utils.ApiR; import com.heyu.api.data.utils.ApiR;
import com.heyu.api.data.utils.R; import com.heyu.api.data.utils.R;
import com.heyu.api.request.doc.ForgeryDetectionRequest; import com.heyu.api.request.doc.ForgeryDetectionRequest;
@ -36,6 +38,7 @@ public class ForgeryDetectionController {
@Autowired @Autowired
private BForgeryDetectionHandle bForgeryDetectionHandle; private BForgeryDetectionHandle bForgeryDetectionHandle;
@EbAuthentication(tencent = ApiConstants.TENCENT_AUTH)
@PostMapping("/forgeryDetection") @PostMapping("/forgeryDetection")
public R<ForgeryDetectionResp> forgeryDetection(@RequestBody ForgeryDetectionRequest request) { public R<ForgeryDetectionResp> forgeryDetection(@RequestBody ForgeryDetectionRequest request) {
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();

View File

@ -7,7 +7,7 @@ import okhttp3.Request;
import okhttp3.RequestBody; import okhttp3.RequestBody;
import okhttp3.Response; import okhttp3.Response;
import java.net.URLEncoder; import java.util.concurrent.TimeUnit;
/** /**
* 图片篡改检测 - 集成测试 * 图片篡改检测 - 集成测试
@ -17,71 +17,113 @@ public class TestForgeryDetection {
private static final String API_KEY = "zs9oN4gSuoS3eK8dVJg6jyKh"; private static final String API_KEY = "zs9oN4gSuoS3eK8dVJg6jyKh";
private static final String SECRET_KEY = "uHIRXkj6rbW1eXy8eRVCeP1e3cRQKXay"; private static final String SECRET_KEY = "uHIRXkj6rbW1eXy8eRVCeP1e3cRQKXay";
private static final OkHttpClient HTTP_CLIENT = new OkHttpClient().newBuilder().build(); private static final OkHttpClient HTTP_CLIENT = new OkHttpClient().newBuilder()
.connectTimeout(30, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.build();
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
// 1. 获取 access_token // 1. 获取 access_token
String accessToken = getAccessToken(); String accessToken = getAccessToken();
System.out.println("access_token: " + accessToken); System.out.println("access_token: " + accessToken.substring(0, 20) + "...");
// 2. 构造请求参数 // 2. 下载图片并转为 base64
String imageUrl = "https://pis.baiwang.com/smkp-vue/previewInvoiceAllEle?param=994386497A3EC72F12692CBDDCC42D051AEA0207F96FABE1B78125CB13A374336BFB46C25F0AC688628DA556C733B4E3F4883E6A0CBA0768E22723D80F925AB9"; // 直接下载图片并转base64避免文件IO问题
String imageUrl = "https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png";
System.out.println("\n下载图片: " + imageUrl);
String imageBase64 = downloadImageAsBase64(imageUrl);
System.out.println("图片base64长度: " + imageBase64.length());
System.out.println("base64前50字符: " + imageBase64.substring(0, Math.min(50, imageBase64.length())));
// 测试1: 基础检测只传图片URL // 测试1: 基础检测base64方式
System.out.println("\n========== 测试1: 基础检测 =========="); System.out.println("\n========== 测试1: 基础检测(base64) ==========");
testBasic(accessToken, imageUrl); testBasicBase64(accessToken, imageBase64);
// 等待避免QPS限制
Thread.sleep(1000);
// 测试2: 带置信度检测 // 测试2: 带置信度检测
System.out.println("\n========== 测试2: 带置信度检测 =========="); System.out.println("\n========== 测试2: 带置信度检测 ==========");
testWithProportion(accessToken, imageUrl); testWithProportion(accessToken, imageBase64);
Thread.sleep(1000);
// 测试3: 带热力图检测 // 测试3: 带热力图检测
System.out.println("\n========== 测试3: 带热力图检测 =========="); System.out.println("\n========== 测试3: 带热力图检测 ==========");
testWithHeatmap(accessToken, imageUrl); testWithHeatmap(accessToken, imageBase64);
} }
private static void testBasic(String accessToken, String imageUrl) throws Exception { private static void testBasicBase64(String accessToken, String imageBase64) throws Exception {
String param = "&url=" + URLEncoder.encode(imageUrl, "UTF-8"); // 测试不编码直接发送与现有BaiduBaseHandle一致
String result = callBaiduApi(accessToken, param); String body = "image=" + imageBase64;
String result = callBaiduApiRaw(accessToken, body);
System.out.println("返回结果:\n" + formatJson(result)); System.out.println("返回结果:\n" + formatJson(result));
parseResult(result); parseResult(result);
} }
private static void testWithProportion(String accessToken, String imageUrl) throws Exception { private static void testWithProportion(String accessToken, String imageBase64) throws Exception {
String param = "&url=" + URLEncoder.encode(imageUrl, "UTF-8") String body = "image=" + imageBase64
+ "&detect_proportion=true"; + "&detect_proportion=true";
String result = callBaiduApi(accessToken, param); String result = callBaiduApiRaw(accessToken, body);
System.out.println("返回结果:\n" + formatJson(result)); System.out.println("返回结果:\n" + formatJson(result));
parseResult(result); parseResult(result);
} }
private static void testWithHeatmap(String accessToken, String imageUrl) throws Exception { private static void testWithHeatmap(String accessToken, String imageBase64) throws Exception {
String param = "&url=" + URLEncoder.encode(imageUrl, "UTF-8") String body = "image=" + imageBase64
+ "&detect_proportion=true" + "&detect_proportion=true"
+ "&return_heatmap=true"; + "&return_heatmap=true";
String result = callBaiduApi(accessToken, param); String result = callBaiduApiRaw(accessToken, body);
System.out.println("返回结果:\n" + formatJson(result)); System.out.println("返回结果:\n" + formatJson(result));
parseResult(result); parseResult(result);
} }
private static String callBaiduApi(String accessToken, String param) throws Exception { private static String downloadImageAsBase64(String url) throws Exception {
if (param.startsWith("&")) { Request request = new Request.Builder().url(url).build();
param = param.substring(1);
}
MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded");
RequestBody body = RequestBody.create(mediaType, param);
Request request = new Request.Builder()
.url("https://aip.baidubce.com/rest/2.0/ocr/v1/forgery_detection?access_token=" + accessToken)
.method("POST", body)
.addHeader("Content-Type", "application/x-www-form-urlencoded")
.addHeader("Accept", "application/json")
.build();
try (Response response = HTTP_CLIENT.newCall(request).execute()) { try (Response response = HTTP_CLIENT.newCall(request).execute()) {
return response.body().string(); byte[] bytes = response.body().bytes();
System.out.println("图片大小: " + bytes.length + " bytes");
return java.util.Base64.getEncoder().encodeToString(bytes);
} }
} }
private static String callBaiduApiRaw(String accessToken, String bodyStr) throws Exception {
java.net.URL url = new java.net.URL("https://aip.baidubce.com/rest/2.0/ocr/v1/forgery_detection?access_token=" + accessToken);
java.net.HttpURLConnection conn = (java.net.HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setDoOutput(true);
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
conn.setRequestProperty("Accept", "application/json");
byte[] bodyBytes = bodyStr.getBytes("UTF-8");
conn.setRequestProperty("Content-Length", String.valueOf(bodyBytes.length));
try (java.io.OutputStream os = conn.getOutputStream()) {
os.write(bodyBytes);
os.flush();
}
try (java.io.BufferedReader reader = new java.io.BufferedReader(
new java.io.InputStreamReader(conn.getInputStream(), "UTF-8"))) {
StringBuilder sb = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
sb.append(line);
}
return sb.toString();
}
}
private static String readBase64FromFile(String filePath) throws Exception {
StringBuilder sb = new StringBuilder();
try (java.io.BufferedReader reader = new java.io.BufferedReader(new java.io.FileReader(filePath))) {
String line;
while ((line = reader.readLine()) != null) {
sb.append(line);
}
}
return sb.toString();
}
private static void parseResult(String result) { private static void parseResult(String result) {
JSONObject json = JSONObject.parseObject(result); JSONObject json = JSONObject.parseObject(result);
@ -130,7 +172,18 @@ public class TestForgeryDetection {
private static String formatJson(String json) { private static String formatJson(String json) {
try { try {
return JSONObject.parseObject(json).toString(); JSONObject obj = JSONObject.parseObject(json);
// 如果有 heatmap截断显示
if (obj.containsKey("result")) {
JSONObject result = obj.getJSONObject("result");
if (result != null && result.containsKey("heatmap")) {
String heatmap = result.getString("heatmap");
if (heatmap != null && heatmap.length() > 50) {
result.put("heatmap", heatmap.substring(0, 50) + "...(共" + heatmap.length() + "字符)");
}
}
}
return obj.toJSONString();
} catch (Exception e) { } catch (Exception e) {
return json; return json;
} }