为什么我的 Ktor 应用程序会在几秒钟后失败?

Why does my Ktor app fail after few seconds?

我有一个小的 Ktor 应用程序(我知道这是一个愚蠢的应用程序,我是一个试图学习 Ktor 的初学者):

import com.auth0.jwt.JWT
import com.auth0.jwt.JWTVerifier
import com.auth0.jwt.algorithms.Algorithm
import io.ktor.application.*
import io.ktor.auth.*
import io.ktor.auth.jwt.*
import io.ktor.features.*
import io.ktor.jackson.*
import io.ktor.response.*
import io.ktor.routing.*
import io.ktor.server.netty.*

private val algorithm = Algorithm.HMAC256("secret")

private fun makeJwtVerifier(issuer: String, audience: String): JWTVerifier = JWT
    .require(algorithm)
    .withAudience(audience)
    .withIssuer(issuer)
    .build()

fun main(args: Array<String>): Unit = EngineMain.main(args)

fun Application.module(testing: Boolean = false) {
    val jwtIssuer = environment.config.property("jwt.domain").getString()
    val jwtAudience = environment.config.property("jwt.audience").getString()
    val jwtRealm = environment.config.property("jwt.realm").getString()

    install(ContentNegotiation) {
        jackson()
    }

    install(Authentication) {
        basic {
            realm = jwtRealm
            validate { credentials ->
                UserIdPrincipal(credentials.name)
            }
        }
        jwt {
            realm = jwtRealm
            verifier(makeJwtVerifier(jwtIssuer, jwtAudience))
            validate { credential ->
                if (credential.payload.audience.contains(jwtAudience)) JWTPrincipal(credential.payload) else null
            }
        }
    }

    routing {
        authenticate("basic") {
            post("/auth/login") {
                val principal = call.principal<UserIdPrincipal>() ?: error ("no auth found")
                call.respondText(principal.name)
            }
        }
    }
}

application.conf:

ktor {
    development = true
    deployment {
        port = 8080
        watch = [ com.contedevel ]
    }
    application {
        modules = [ com.contedevel.backend.ApplicationKt.module ]
    }
    jwt {
        domain = "https://localhost/"
        audience = "jwt-audience"
        realm = "acupoftea"
    }
}

我的build.gradle.kts:

import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
    application
    kotlin("jvm") version "1.4.30"
}

group = "com.contedevel"
version = "1.0-SNAPSHOT"

application {
    mainClass.set("io.ktor.server.netty.EngineMain")
}

repositories {
    mavenCentral()
}

dependencies {
    // Standard
    implementation(kotlin("stdlib"))
    // Ktor
    implementation("io.ktor:ktor-server-core:1.5.2")
    implementation("io.ktor:ktor-server-netty:1.5.2")
    implementation("ch.qos.logback:logback-classic:1.2.1")
    // Jackson
    implementation("io.ktor:ktor-jackson:1.5.2")
    // JWT
    implementation("io.ktor:ktor-auth:1.5.2")
    implementation("io.ktor:ktor-auth-jwt:1.5.2")
    // Testing
    testImplementation(kotlin("test-junit"))
}

tasks.test {
    useJUnit()
}

tasks.withType<KotlinCompile>() {
    kotlinOptions.jvmTarget = "13"
}

然后我尝试通过 ./gradlew run 启动应用程序,它显示了一些警告但失败了:

01:53:18.381 [Thread-0] DEBUG io.netty.util.internal.NativeLibraryLoader - netty_transport_native_kqueue cannot be loaded from java.library.path, now trying export to -Dio.netty.native.workdir: /var/folders/d5/x8gp_xv95xb0l5y3_gq_m1840000gn/T
java.lang.UnsatisfiedLinkError: no netty_transport_native_kqueue in java.library.path: /Users/denis/Library/Java/Extensions:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java:.
        at java.base/java.lang.ClassLoader.loadLibrary(ClassLoader.java:2447)
        at java.base/java.lang.Runtime.loadLibrary0(Runtime.java:809)
        at java.base/java.lang.System.loadLibrary(System.java:1893)
        at io.netty.util.internal.NativeLibraryUtil.loadLibrary(NativeLibraryUtil.java:38)
        at io.netty.util.internal.NativeLibraryLoader.loadLibrary(NativeLibraryLoader.java:351)
        at io.netty.util.internal.NativeLibraryLoader.load(NativeLibraryLoader.java:136)
        at io.netty.channel.kqueue.Native.loadNativeLibrary(Native.java:128)
        at io.netty.channel.kqueue.Native.<clinit>(Native.java:60)
        at io.netty.channel.kqueue.KQueue.<clinit>(KQueue.java:37)
        at io.ktor.server.netty.EventLoopGroupProxy$Companion.create(NettyApplicationEngine.kt:232)
        at io.ktor.server.netty.NettyApplicationEngine$workerEventGroup.invoke(NettyApplicationEngine.kt:98)
        at io.ktor.server.netty.NettyApplicationEngine$workerEventGroup.invoke(NettyApplicationEngine.kt:28)
        at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74)
        at io.ktor.server.netty.NettyApplicationEngine.getWorkerEventGroup(NettyApplicationEngine.kt)
        at io.ktor.server.netty.NettyApplicationEngine.access$getWorkerEventGroup$p(NettyApplicationEngine.kt:28)
        at io.ktor.server.netty.NettyApplicationEngine$engineDispatcherWithShutdown.invoke(NettyApplicationEngine.kt:118)
        at io.ktor.server.netty.NettyApplicationEngine$engineDispatcherWithShutdown.invoke(NettyApplicationEngine.kt:28)
        at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74)
        at io.ktor.server.netty.NettyApplicationEngine.getEngineDispatcherWithShutdown(NettyApplicationEngine.kt)
        at io.ktor.server.netty.NettyApplicationEngine.stop(NettyApplicationEngine.kt:181)
        at io.ktor.server.engine.ApplicationEngineJvmKt.stop(ApplicationEngineJvm.kt:18)
        at io.ktor.server.netty.EngineMain$main.invoke(EngineMain.kt:24)
        at io.ktor.server.netty.EngineMain$main.invoke(EngineMain.kt:14)
        at io.ktor.server.engine.ShutdownHook.run(ShutdownHook.kt:37)
        Suppressed: java.lang.UnsatisfiedLinkError: no netty_transport_native_kqueue in java.library.path: /Users/denis/Library/Java/Extensions:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java:.
                at java.base/java.lang.ClassLoader.loadLibrary(ClassLoader.java:2447)
                at java.base/java.lang.Runtime.loadLibrary0(Runtime.java:809)
                at java.base/java.lang.System.loadLibrary(System.java:1893)
                at io.netty.util.internal.NativeLibraryUtil.loadLibrary(NativeLibraryUtil.java:38)
                at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
                at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64)
                at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
                at java.base/java.lang.reflect.Method.invoke(Method.java:564)
                at io.netty.util.internal.NativeLibraryLoader.run(NativeLibraryLoader.java:385)
                at java.base/java.security.AccessController.doPrivileged(AccessController.java:312)
                at io.netty.util.internal.NativeLibraryLoader.loadLibraryByHelper(NativeLibraryLoader.java:377)
                at io.netty.util.internal.NativeLibraryLoader.loadLibrary(NativeLibraryLoader.java:341)
                ... 19 common frames omitted
01:53:18.394 [Thread-0] DEBUG io.netty.channel.MultithreadEventLoopGroup - -Dio.netty.eventLoopThreads: 24
01:53:18.401 [Thread-0] DEBUG io.netty.util.internal.InternalThreadLocalMap - -Dio.netty.threadLocalMap.stringBuilder.initialSize: 1024
01:53:18.401 [Thread-0] DEBUG io.netty.util.internal.InternalThreadLocalMap - -Dio.netty.threadLocalMap.stringBuilder.maxSize: 4096
01:53:18.404 [Thread-0] DEBUG io.netty.channel.nio.NioEventLoop - -Dio.netty.noKeySetOptimization: false
01:53:18.404 [Thread-0] DEBUG io.netty.channel.nio.NioEventLoop - -Dio.netty.selectorAutoRebuildThreshold: 512
01:53:18.408 [Thread-0] DEBUG io.netty.util.internal.PlatformDependent - org.jctools-core.MpscChunkedArrayQueue: available

> Task :run FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':run'.
> Process 'command '/Library/Java/JavaVirtualMachines/liberica-jdk-15-full.jdk/Contents/Home/bin/java'' finished with non-zero exit value 1

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 8s

但是,当我调用 ./gradlew build 时,一切都成功了...我的错误是什么?

P.S. 我用 Liberica JDK v.15.

我在 运行 你的应用程序时遇到两个错误:

  1. Property jwt.audience not found。这个错误和类似的错误可以通过传递所需的参数来修复:./gradlew run -P:jwt.domain=domain -P:jwt.audience=audience -P:jwt.realm=realm
  2. Provider with the name null is already registered。这是由于未命名提供程序的名称冲突造成的,可以通过显式命名来解决:

修改后的代码如下:

install(Authentication) {
    basic("basic") {
        realm = jwtRealm
        validate { credentials ->
            UserIdPrincipal(credentials.name)
        }
    }
    jwt("jwt") {
        realm = jwtRealm
        verifier(makeJwtVerifier(jwtIssuer, jwtAudience))
        validate { credential ->
            if (credential.payload.audience.contains(jwtAudience)) JWTPrincipal(credential.payload) else null
        }
    }
}