使用 JSON 格式的 log4j 记录 json 字符串消息,而不用引号破坏格式
Posted
技术标签:
【中文标题】使用 JSON 格式的 log4j 记录 json 字符串消息,而不用引号破坏格式【英文标题】:log json string message using log4j in JSON format without breaking the format with quotes 【发布时间】:2022-01-24 04:40:18 【问题描述】:我正在尝试以 json 格式格式化日志并使用模式布局来执行此操作。但是生成的输出不是正确的 json 格式,因为 msg 中的额外引号正在被记录。
下面是 log4j.properties 文件 =======================log4j.properties==================
appender.file.layout.pattern="level":"%p","time":"%dISO8601","thread":"%t","file":"%F", "line":"%L","message":"%m"%n
loggers=file
logger.file.name=com.ibm
logger.file.level = error
logger.file.level = debug
logger.file.appenderRefs = file
logger.file.appenderRef.file.ref = LOGFILE
rootLogger.level = error
rootLogger.level = debug
rootLogger.appenderRefs = stdout
rootLogger.appenderRef.stdout.ref = STDOUT
下面是编码格式
String msg = "!@#$%^&*()_+=~[]|<>?;'Text with special character /\"\'\b\f\t\r\n";
// to escape especial character, serializing msg with jackson library method
Serialize serializeMsg = objectMapper.writeValueAsString(msg);
String jsonString = "" + serializeMsg + "\", \"crn\":\"" + crn + "\", \"otherProperty\":\"" + crn + "\"";
log.debug(serializeMsg );
Json 日志生成
"level":"DEBUG","time":"2021-12-20T20:05:14,465","thread":"main","file":"App.java", "line":"81","message":""!@#$%^&*()_+=~[]|<>?;'Text with special character /\"'\b\f\t\r\n"", "crn":"5741af48-808a-4e55-8f37-681f025b1ce3", "otherProperty":"5741af48-808a-4e55-8f37-681f025b1ce3""
如何从邮件中删除多余的引号?谢谢!!
【问题讨论】:
【参考方案1】:直接回答你的问题:objectMapper.writeValueAsString(msg)
输出一个有效的 JSON,因此它是一个用双引号括起来的字符串。您在代码中构造的消息是:
"!@#$%^&*()_+=~[]|<>?;'Text with special character /\"'\b\f\t\r\n"", "crn":"5741af48-808a-4e55-8f37-681f025b1ce3", "otherProperty":"5741af48-808a-4e55-8f37-681f025b1ce3"
您的PatternLayout
将其括在另一对双引号中("%m"
)。您可以轻松地从代码中删除一些双引号,使其成为有效的 JSON 消息。
但是,您为解决主要问题(将日志消息格式化为 JSON)而采取的整个方法是不稳定的(这是一个大问题):您需要应用程序中的所有日志消息都具有类似于 JSON 的格式。如果您忘记正确格式化消息会发生什么?那些肯定不符合您的格式的图书馆消息怎么办?如果您的应用程序的用户想要更改日志记录布局会发生什么?如果您不小心记录的内容,您的方法也可能容易受到log injection attacks 的攻击。
一种标准方法是让 Log4j 将您的消息格式化为 JSON。有一个JSON Template Layout。你只需要:
将log4j-layout-template-json
添加到您的依赖项中,
在您的应用程序类路径中创建一个模板(我们称之为logTemplate.json
):
"level":
"$resolver": "level",
"field": "name"
,
"time":
"$resolver": "timestamp"
,
"thread":
"$resolver": "thread",
"field": "name"
,
"file":
"$resolver": "source",
"field": "fileName"
,
"line":
"$resolver": "source",
"field": "lineNumber"
,
"message":
"$resolver": "message",
"stringified": true
更新您的 log4j2.properties
文件以使用 JSON 模板布局:
appender.file.layout.type=JsonTemplateLayout
appender.file.layout.eventTemplateUri=classpath:logTemplate.json
appender.file.layout.locationInfoEnabled=true
只需调用即可记录消息:
log.debug("!@#$%^&*()_+=~[]|<>?;'Text with special character /\"\'\b\f\t\r\n");
【讨论】:
感谢您回答问题并提出解决问题的更好方法。实际上,客户端现在可能不允许我们添加任何进一步的依赖项,所以不幸的是,我可能不得不采用从代码本身中删除引号的解决方案,现在我得到了有效 json 格式的输出。再次感谢您的建议。 由于您之前描述的所有安全问题,肯定会更新为 json 模板布局。接受您的评论作为答案。以上是关于使用 JSON 格式的 log4j 记录 json 字符串消息,而不用引号破坏格式的主要内容,如果未能解决你的问题,请参考以下文章