我正在为我的 Android 应用程序使用 KTor https 服务器,我注意到尝试连接到我的服务器的机器人由于未发生 TLS 握手而失败。 这很烦人,因为我的日志文件中充满了 netty 的 SL4J 记录器的 WARN 标签的巨大转储。 有没有办法在不引起错误/警告的情况下处理此类客户端? 我尝试在 Ktor 中使用请求验证插件,但它不起作用。 这是我的 logback.xml:
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{dd-MM-YYYY HH:mm:ss.SSS} [%thread] [%-5level] %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="trace">
<appender-ref ref="STDOUT"/>
</root>
<logger name="org.eclipse.jetty" level="WARN"/>
<logger name="io.netty" level="WARN"/>
<logger name="io.ktor" level="WARN"/>
</configuration>
这是 /plugins 文件夹中 Validation.kt 中我的请求验证函数:
fun Application.configureValidation() {
println("Inside application validation")//this is printed at app startup
install(RequestValidation) {
validate<String> {bodyText ->
if (bodyText.contains("mySite")) {
println("Received request validation text: $bodyText")//this is never printed
ValidationResult.Valid
}
else if (bodyText.contains("myApp")) {
println("Received request validation text: $bodyText")//this is never printed
ValidationResult.Valid
}
else {
println("Received request validation text: $bodyText")//this is never printed
ValidationResult.Invalid("Request Validation failed for bot")
}
}
validate {
filter { body ->
body is Any
}
validation { body ->
println("Received request validation 2 text: $body")//this is never printed
if(body.toString().isNullOrEmpty())
ValidationResult.Invalid("Request Validation failed because its empty")
else
ValidationResult.Valid
}
}
}
println("After application validation")//this is printed at app startup
}
接收到的请求验证 println 均不会打印在日志文件中。
这是在我的Application.kt中:
fun Application.module() {
printMyStr("Inside Application")
configureValidation()
printMyStr("After validation")
install(StatusPages) {
exception<RequestValidationException> { call, cause ->
call.respond(HttpStatusCode.BadRequest, cause.reasons.joinToString())
}
}
install(ContentNegotiation) {
json()
}
printMyStr("Before socket")
configureSockets()
printMyStr("Before routing")
configureRouting()
printMyStr("After routing")
}
我的日志文件中的转储消息示例:
29-09-2023 18:39:13.240 [eventLoopGroupProxy-3-1] [WARN ] i.n.h.s.ApplicationProtocolNegotiationHandler - [id: 0x54c76869, L:0.0.0.0/0.0.0.0:1234 ! R:/34.756.619.638:9375] TLS handshake failed:
io.netty.handler.ssl.NotSslRecordException: not an SSL/TLS record: 0300002f2ae00000000000436f6f6b69653a206d737473686173683d41646d696e697374720d0a0100080003000000
at io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1225)
at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1295)
at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:529)
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:468)
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:290)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:440)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:788)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:724)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:650)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562)
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at io.ktor.server.netty.EventLoopGroupProxy$Companion.create$lambda$1$lambda$0(NettyApplicationEngine.kt:296)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.lang.Thread.run(Thread.java:750)
30-09-2023 04:06:41.006 [eventLoopGroupProxy-3-1] [WARN ] i.n.h.s.ApplicationProtocolNegotiationHandler - [id: 0xe8b12e42, L:0.0.0.0/0.0.0.0:1234 ! R:/432.690.528.47:9264] TLS handshake failed:
io.netty.handler.ssl.NotSslRecordException: not an SSL/TLS record: 0100000000cd00010000414e592d5343502020202020202020204543484f534355202020202020202020000000000000000000000000000000000000000000000000000000000000000010000015312e322e3834302e31303030382e332e312e312e312000002e0100ff0030000011312e322e3834302e31303030382e312e3140000011312e322e3834302e31303030382e312e325000003a51000004000040005200001b312e322e3237362e302e373233303031302e332e302e332e362e325500000f4f464649535f44434d544b5f333632
at io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1225)
at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1295)
at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:529)
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:468)
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:290)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:440)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:788)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:724)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:650)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562)
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at io.ktor.server.netty.EventLoopGroupProxy$Companion.create$lambda$1$lambda$0(NettyApplicationEngine.kt:296)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.lang.Thread.run(Thread.java:750)
按照 Aleksei 在上面评论中的建议,使用 Janino 过滤异常不起作用。 这是我的 logback.xml:
<configuration>
<evaluator name="NotSslRecordExceptionSuppressor">
<expression>throwable != null && throwable instanceof io.netty.handler.ssl.NotSslRecordException</expression>
</evaluator>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{dd-MM-YYYY HH:mm:ss.SSS} [%thread] [%-5level] %logger{36} - %msg %ex{full,InvalidLoginExceptionSuppressor}%n</pattern>
<immediateFlush>false</immediateFlush>
</encoder>
</appender>
<root level="trace">
<appender-ref ref="STDOUT"/>
</root>
<logger name="org.eclipse.jetty" level="WARN"/>
<logger name="io.netty" level="WARN"/>
<logger name="io.ktor" level="WARN"/>
</configuration>
以下内容现在打印在我的日志文件中:
16:21:55,761 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback-test.xml]
16:21:55,761 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Found resource [logback.xml] at [jar:file:/mypath/abc.jar!/logback.xml]
16:21:55,848 |-INFO in ch.qos.logback.core.joran.spi.ConfigurationWatchList@49e202ad - URL [jar:file:/mypath/abc.jar!/logback.xml] is not of type file
16:21:56,166 |-INFO in ch.qos.logback.classic.joran.action.ConfigurationAction - debug attribute not set
16:21:56,178 |-INFO in ch.qos.logback.classic.joran.action.EvaluatorAction - Assuming default evaluator class [ch.qos.logback.classic.boolex.JaninoEventEvaluator]
16:21:56,180 |-INFO in ch.qos.logback.classic.joran.action.EvaluatorAction - Adding evaluator named [NotSslRecordExceptionSuppressor] to the object stack
16:21:56,373 |-INFO in ch.qos.logback.classic.boolex.JaninoEventEvaluator@1c72da34 - Adding [return] prefix and a semicolon suffix. Expression becomes [return throwable != null && throwable instanceof io.netty.handler.ssl.NotSslRecordException;]
16:21:56,373 |-INFO in ch.qos.logback.classic.boolex.JaninoEventEvaluator@1c72da34 - See also http://logback.qos.ch/codes.html#block
16:21:57,300 |-INFO in ch.qos.logback.classic.joran.action.EvaluatorAction - Starting evaluator named [NotSslRecordExceptionSuppressor]
16:21:57,300 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - About to instantiate appender of type [ch.qos.logback.core.ConsoleAppender]
16:21:57,338 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - Naming appender as [STDOUT]
16:21:57,349 |-INFO in ch.qos.logback.core.joran.action.NestedComplexPropertyIA - Assuming default type [ch.qos.logback.classic.encoder.PatternLayoutEncoder] for [encoder] property
16:21:57,360 |-WARN in ch.qos.logback.classic.encoder.PatternLayoutEncoder@6b0c2d26 - As of version 1.2.0 "immediateFlush" property should be set within the enclosing Appender.
16:21:57,360 |-WARN in ch.qos.logback.classic.encoder.PatternLayoutEncoder@6b0c2d26 - Please move "immediateFlush" property into the enclosing appender.
16:21:57,649 |-WARN in ch.qos.logback.classic.encoder.PatternLayoutEncoder@6b0c2d26 - Setting the "immediateFlush" property of the enclosing appender to false
16:21:57,650 |-INFO in ch.qos.logback.classic.joran.action.RootLoggerAction - Setting level of ROOT logger to TRACE
16:21:57,650 |-INFO in ch.qos.logback.core.joran.action.AppenderRefAction - Attaching appender named [STDOUT] to Logger[ROOT]
16:21:57,650 |-INFO in ch.qos.logback.classic.joran.action.LoggerAction - Setting level of logger [org.eclipse.jetty] to WARN
16:21:57,651 |-INFO in ch.qos.logback.classic.joran.action.LoggerAction - Setting level of logger [io.netty] to WARN
16:21:57,671 |-INFO in ch.qos.logback.classic.joran.action.LoggerAction - Setting level of logger [io.ktor] to WARN
16:21:57,671 |-INFO in ch.qos.logback.classic.joran.action.ConfigurationAction - End of configuration.
16:21:57,671 |-INFO in ch.qos.logback.classic.joran.JoranConfigurator@3d3fcdb0 - Registering current configuration as safe fallback point
由于这不起作用并打印以下静态内容:
24-11-2023 16:22:09.749 [eventLoopGroupProxy-3-1] [WARN ] i.n.h.s.ApplicationProtocolNegotiationHandler - [id: 0x25f5cf98, L:0.0.0.0/0.0.0.0:1234 ! R:/415.589.36.796:9666] TLS handshake failed: io.netty.handler.ssl.NotSslRecordException: not an SSL/TLS record: 474554202f746570706c655765624b69742f3533372e333620284b48544d4c2c206c696b65204765636b6f29204368726f6d652f3131392e302e302e30205361666172692f3533372e33360d0a4163636570743a20746578742f68746d6c2c6170706c69636174696f6e2f7868746d6c2b786d6c2c6170706c69636174696f6e2f786d6c3b713d302e392c696d6167652f617669662c696d6167652f776562702c696d6167652f61706e672c2a2f2a3b713d302e382c6170706c69636174696f6e2f7369676e65642d65786368616e67653b763d62333b713d302e370d0a4163636570742d456e636f64696e673a20677a69702c206465666c6174650d0a4163636570742d4c616e67756167653a20656e2d55532c656e3b713d302e390d0a0d0a
at io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1225)
at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1295)
因此,解决我的问题的唯一解决方案似乎是将记录器更改为仅在 logback.xml 中打印错误级别消息而不是警告级别:
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{dd-MM-YYYY HH:mm:ss.SSS} [%thread] [%-5level] %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="trace">
<appender-ref ref="STDOUT"/>
</root>
<logger name="org.eclipse.jetty" level="WARN"/>
<logger name="io.netty" level="ERROR"/>
<logger name="io.ktor" level="WARN"/>
</configuration>