我在 Spring boot 项目中面临一个奇怪的问题,其中主体在控制器中不可检索。 这有点具体:我正在使用 bc tls psk 方案与 SIM 卡通信,并且它已经工作了好几年,没有出现任何故障,但是现在当与特定卡/设备交换时,卡发送的有效负载在以下位置不可用我的控制器。
我正在使用 Springboot 2.5.15、Java 8、BC jdk8on 1.78.1。
我进行了 tcpdump 跟踪,我确实看到了有效负载 AF 80 23 11 .. .. 00 00 (SIM 卡是这样说话的,请不要评判它们!)。 所以我无法检索该有效负载即使它存在于两者TCP跟踪和内容长度标头告诉我它在那里。
这是 TCPDUMP 屏幕截图:
我的控制器:
public void anyRequest(@RequestHeader(value = CONTENT_TYPE, required = false) String requestContentType,
@RequestHeader(value = HEADER_X_ADMIN_PROTOCOL) String adminProtocol,
@RequestHeader(value = HEADER_X_ADMIN_FROM) String adminFrom,
@RequestHeader(value = HEADER_X_ADMIN_RESUME, required = false, defaultValue = "false") boolean adminResume,
@RequestHeader(value = HEADER_X_ADMIN_SCRIPT_STATUS, required = false) String adminScriptStatus,
@RequestBody(required = false) byte[] body, final HttpServletRequest request,
final HttpServletResponse response) throws InterruptedException, IOException {
在那里我通常会得到这样的身体:
Long contentLength = request.getContentLengthLong();
log.info("Request Content lenght in header: {}", contentLength);
if (body != null) {
log.info("body content {} ", Hex.encodeHexString(body));
}
再次强调,它在 99% 的情况下都有效。但是当我使用特定设备时,它不会,body 保持为空。
我什至尝试过其他几种方式来获得它,但没有运气
尝试数字1:
if (body == null && contentLength > 0) {
log.warn("Body seems null while Content length Header is {} ", contentLength);
log.info("Trying alternative way to retreive the body {} ", contentLength);
InputStream is = request.getInputStream();
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int nRead;
byte[] data = new byte[16384];
while ((nRead = is.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
}
body = buffer.toByteArray();
}
尝试数字 2:(这实际上是返回一个由零组成的字节数组,但值得尝试)
private byte[] alternateBodybytes(InputStream serveltInputStream, int contentLength) throws IOException {
byte[] bytes = new byte[contentLength];
for (int r, offset = 0; (r = serveltInputStream.read(bytes, offset, bytes.length - offset)) > -1;) {
offset += r;
}
return bytes;
}
我现在没有选项了,正在寻找建议,如果你们有的话?
你觉得怎么样?有什么建议吗?
注意:下面是一个交易的 TCP 跟踪,我可以从 @RequestBody(required = false) byte[] body 获取正文,对我来说,它看起来完全一样,对吧?
评论建议我使用 StreamUtils 和/或 ContentCachingRequestWrapper 来确保我的 bodyu 尚未被消耗。我使用了 iun 序列,但仍然没有看到所需的内容。
public void anyRequest(@RequestHeader(value = CONTENT_TYPE, required = false) String requestContentType,
@RequestHeader(value = HEADER_X_ADMIN_PROTOCOL) String adminProtocol,
@RequestHeader(value = HEADER_X_ADMIN_FROM) String adminFrom,
@RequestHeader(value = HEADER_X_ADMIN_RESUME, required = false, defaultValue = "false") boolean adminResume,
@RequestHeader(value = HEADER_X_ADMIN_SCRIPT_STATUS, required = false) String adminScriptStatus,
@RequestBody(required = false) byte[] body, final HttpServletRequest request,
final HttpServletResponse response) throws InterruptedException, IOException {
ContentCachingRequestWrapper requestWrapper = (ContentCachingRequestWrapper) request;
[...]
if (body == null && contentLength > 0) {
log.warn("Body seems null while Content length Header is {} ", contentLength);
log.info("Trying alternative way #1 to retreive the body using requestWrapper");
byte[] requestPayload = requestWrapper.getContentAsByteArray();
if (requestPayload != null && requestPayload.length > 0) {
log.info("Managed to retreive a body of length {} ", requestPayload.length);
log.info("alternative body content {} ", Hex.encodeHexString(requestPayload));
body = requestPayload;
} else {
log.warn("Couldnt get the content body using Method 1");
log.warn("Trying alternative way #2 to retreive the body using alternateBodybytes2");
requestPayload = requestPayload = StreamUtils.copyToByteArray(requestWrapper.getInputStream());
if (requestPayload != null) {
log.info("Managed to retreive a body of length {} ", requestPayload.length);
log.trace("alternative 2 body content {} ", Hex.encodeHexString(requestPayload));
} else {
log.error("Couldnt extract body content");
}
}
body = requestPayload;
}
以下日志的结果相同:
2024-09-30 09:24:56.149 INFO 4165202 --- [https-psk-bc-nio2-9100-exec-25] c.c.RemoteAdministrationServerController : Request Content length in header: 23
2024-09-30 09:24:56.149 WARN 4165202 --- [https-psk-bc-nio2-9100-exec-25] c.c.RemoteAdministrationServerController : Body seems null while Content length Header is 23
2024-09-30 09:24:56.149 INFO 4165202 --- [https-psk-bc-nio2-9100-exec-25] c.c.RemoteAdministrationServerController : Trying alternative way #1 to retreive the body using requestWrapper
2024-09-30 09:24:56.149 WARN 4165202 --- [https-psk-bc-nio2-9100-exec-25] c.c.RemoteAdministrationServerController : Couldnt get the content body using Method 1
2024-09-30 09:24:56.149 WARN 4165202 --- [https-psk-bc-nio2-9100-exec-25] c.c.RemoteAdministrationServerController : Trying alternative way #2 to retreive the body using alternateBodybytes2
@网络列车
这里是TCP层的差异,可能是因为重新组装的数据包?你看到什么奇怪的东西了吗?
交易失败
交易成功: