Ohhnews

分类导航

$ cd ..
Jetbrains Blog原文

Ktor 3.6.0 发布:新增类型安全认证、OpenID Connect 与 Netty HTTP/3 支持

#ktor#kotlin multiplatform#类型安全认证#openid connect#http/3

Ktor 3.6.0 来了!此版本包含大量新的实验性功能,包括类型化身份验证能力,以及对 OpenID Connect 的专门支持和 Netty 引擎的 HTTP/3 支持。此外还有一些针对路由和请求处理的体验优化、为 Kotlin Multiplatform 客户端提供的更便捷默认配置等。请在我们的网站上查看 Ktor 3.6.0 有哪些新变化,了解完整的变更列表,或查看发布说明。

🚀 开始使用 Ktor 3.6.0

准备好探索 Ktor 3.6.0 了吗?使用 start.ktor.io 上的交互式项目生成器开始你的下一个项目。我们始终欢迎你的反馈和贡献!
开始使用 Ktor 3.6.0

类型化身份验证

到目前为止,Ktor 的身份验证一直依赖隐式类型来将配置与路由连接起来。在这个模块中,你可以获得新的类型,从而在处理复杂身份验证时保证完整的类型安全。它还支持基于角色的访问控制和匿名用户。通过利用上下文参数,我们能够实现更优雅的语法。请阅读类型安全身份验证文档,了解设置、角色检查和失败处理。

$ kotlin
val jwtAuth = jwt<User>("my-jwt") {
    verifier(jwkProvider, issuer)
    validate { credential ->
        val payload = credential.payload
        User(
            id = payload.subject,
            email = payload.getClaim("email").asString()
        )
    }
}

routing {
    authenticateWith(jwtAuth) {
        get("/profile") {
            val user = call.principal
            call.respondText(user)
        }
    }
}

OpenID Connect

新的 OpenID Connect(Oidc)插件旨在降低通过 OpenID Connect 提供程序保护服务时的复杂性。Oidc 插件允许你创建类型化的身份验证提供程序,以类型化方式支持所有 OpenID Connect 功能。它还支持会话、带自动刷新令牌的浏览器登录界面等。完整文档请查看 Ktor 网站——这里

$ kotlin
suspend fun Application.module() {
    val oidc = install(Oidc)

    val auth0 = oidc.identityProvider("auth0") {
        issuer = "https://my-tenant.auth0.com"
        bearer {
            audience = setOf("https://api.example.com")
        }
    }

    routing {
        authenticateWith(auth0.jwtBearer) {
            get("/orders") {
                val subject = call.principal.claims.subject
                call.respondText("Hello $subject")
            }
        }
    }
}

更多 Netty 功能

Netty 服务器引擎现在通过 QUIC 提供实验性的 HTTP/3 支持。要启用它,请配置 SSL 连接器,然后使用 enableHttp3 { } 选择启用:

$ kotlin
embeddedServer(Netty, environment, {
    sslConnector(
        keyStore = keyStore,
        keyAlias = "server",
        keyStorePassword = { "changeit".toCharArray() },
        privateKeyPassword = { "changeit".toCharArray() }
    ) { port = 8443 }

    enableHttp3 { quicMaxIdleTimeout = 30.seconds }
}) { /* application */ }.start(wait = true)

enableHttp3 {} 代码块还允许你调整 QUIC 特有的设置,例如流量控制限制和 UDP socket 配置。它仍处于实验阶段,所以如果你决定尝试,我们非常期待你的反馈。

Netty 服务器现在还可以在一个连接器上提供 h2c,并在另一个连接器上通过 TLS 提供 HTTP/2。通过 enableH2c = trueenableHttp2 = true 同时启用两者。

$ kotlin
embeddedServer(Netty, configure = {
    connector { port = 8080 }
    sslConnector(...) { port = 8443 }

    enableHttp2 = true
    enableH2c = true
}) { /* application */ }.start(wait = true)

更高效的路由处理器

请求参数转换现在支持 Kotlin 的 UuidByte 和无符号数值类型。ApplicationCall.receive() 现在也接受可空类型,使路由契约更加明确,并弃用 receiveNullable()

$ kotlin
put("/users/{id}") {
    val id: Uuid by call.parameters
    val preferences = call.receive<NotificationPreferences?>()

    if (preferences == null) {
        preferenceService.clear(id)
    } else {
        preferenceService.update(id, preferences)
    }
    call.respond(HttpStatusCode.NoContent)
}

我们还添加了 respondHtmlPartial,用于替代已弃用的 respondHtmlFragment。新函数使用 TagConsumer<Appendable>,因此可以返回不受限制的部分 HTML——支持 FlowContent 支持的所有元素。

$ kotlin
get("/status") {
    call.respondHtmlPartial(HttpStatusCode.OK) {
        td { +"Ready" }
    }
}

更好地控制 ContentNegotiation

客户端 ContentNegotiation 插件过去会将其注册的内容类型合并到每个 Accept 头中。这通常很有帮助,但当 API 期望你在请求中设置的该头保持原样时,就不合适了。

使用 ContentTypeMergeStrategy.SkipIfPresent 时,显式的 Accept 头优先。当请求没有 Accept 头时,插件会照常继续添加已注册的内容类型:

$ kotlin
install(ContentNegotiation) {
    register(ContentType.Application.Json, noOpJsonConverter)
    acceptHeaderMergeStrategy = ContentTypeMergeStrategy.SkipIfPresent
}

更简单的 Kotlin Multiplatform 客户端

Ktor 3.6.0 引入了 ktor-client-engine-defaults:一组为 Kotlin Multiplatform 项目精心挑选的客户端引擎。将其添加到 commonMain,即可在共享代码中创建 HttpClient() 而无需选择引擎。Ktor 会为每个目标选择适当的可用引擎。

HTTP 缓存也朝着同一方向改进。基于文件的缓存存储现在使用 kotlinx-ioPath,因此持久化的 HttpCache 存储不再局限于 JVM 的 java.io.File API。这些改进共同使设置带简单缓存的 KMP 客户端变得容易得多:

$ kotlin
// build.gradle.kts
kotlin {
    sourceSets {
        commonMain {
            dependencies {
                api("io.ktor:ktor-client-engine-defaults:3.6.0")
            }
        }
    }
}

// Main.kt
val client = HttpClient() {
    install(HttpCache) {
        publicStorage(FileStorage(Path("build/cache")))
    }
}

这为 Ktor 项目提供了更自然的公共代码设置方式,同时保留在平台需要时选择并配置特定引擎的选项。

有关 3.6.0 变更的完整列表,包括 JVM 的 WebRTC 支持、CIO 的异步 DNS 解析、OpenAPI 标签描述、重复 cookie 解析以及 JavaScript fetch() 覆盖等,请参阅 Ktor 3.6.0 有哪些新变化

🙏 谢谢!

感谢社区中的每一个人,感谢你们的反馈、问题报告和贡献,它们帮助每个 Ktor 版本变得更好。特别感谢其工作被纳入此版本的外部贡献者:kdelay、Rafa Ruiz 和 solo。

start.ktor.io 开始构建你的下一个项目。我们始终欢迎你的建议和贡献!

👉 开始使用 Ktor | 💬 在 Slack 上加入社区