@@ -438,26 +438,30 @@ private String requireConnectValue(String value, String name) {
438438 /**
439439 * 对 connect BODY 调试日志中的认证材料和设备签名脱敏。
440440 *
441+ * <p>基于深拷贝构造仅用于日志的脱敏副本,解析出的原始树保持只读;副本为调用线程私有,
442+ * 因此本方法天然线程安全,可在任意线程(如 WebSocket 读线程)并发调用。</p>
443+ *
441444 * @param json 原始 connect 请求 JSON
442445 * @return 保留协议结构但不包含认证秘密和设备签名的 JSON
443446 */
444447 String redactConnectHandshake (String json ) {
445448 try {
446449 JsonNode root = objectMapper .readTree (json );
450+ JsonNode sanitized = root .deepCopy ();
447451 JsonNode auth = root .path ("params" ).path ("auth" );
448452 if (auth .isObject ()) {
449- java . util . Collection < String > names = auth . propertyNames ();
450- while (! names . isEmpty ()) {
451- (( tools . jackson . databind . node . ObjectNode ) auth )
452- .put (names . iterator (). next () , "<redacted>" );
453+ tools . jackson . databind . node . ObjectNode sanitizedAuth =
454+ ( tools . jackson . databind . node . ObjectNode ) sanitized . path ( "params" ). path ( "auth" );
455+ for ( String name : auth . propertyNames ()) {
456+ sanitizedAuth .put (name , "<redacted>" );
453457 }
454458 }
455459 JsonNode device = root .path ("params" ).path ("device" );
456460 if (device .isObject () && device .has ("signature" )) {
457- ((tools .jackson .databind .node .ObjectNode ) device )
461+ ((tools .jackson .databind .node .ObjectNode ) sanitized . path ( "params" ). path ( " device" ) )
458462 .put ("signature" , "<redacted>" );
459463 }
460- return objectMapper .writeValueAsString (root );
464+ return objectMapper .writeValueAsString (sanitized );
461465 } catch (JacksonException e ) {
462466 return "<connect-payload-redacted>" ;
463467 }
0 commit comments