Ktor 3.5.0 的新功能
Ktor 3.5.0 的新功能
Ktor 3.5.0 針對伺服器與用戶端提供了一系列改進。本次功能發布的重點包括:
- 支援 RFC 7616 摘要驗證 (Digest authentication)
- 根配置 (Root configuration) data class 對應
- 僅在修改時傳送工作階段 Cookie
- OkHttp 與 Apache5 用戶端引擎中的自訂 DNS 解析器
Ktor Server
支援 RFC 7616 摘要驗證 (Digest authentication)
Ktor 3.5.0 更新了 digest 驗證提供者以符合 RFC 7616 規範,提升了安全性並增加了對現代 Digest 功能的支援。
本次發布引入了以下變更:
- 您現在可以使用
algorithms屬性配置多個雜湊演算法。當指定多個值時,Ktor 會傳送多個WWW-Authenticate標頭,以便用戶端可以選擇支援的最強選項。 - 引入了
DigestAlgorithm與DigestQop列舉 (enums) 以取代基於字串的配置。 digestProvider {}lambda 現在會接收一個algorithm參數,允許您動態計算正確的摘要。- 根據 RFC 7616,
qop參數現在已包含在驗證挑戰 (authentication challenges) 中。 - 增加了對基於工作階段 (session-based) 演算法的支援,例如
SHA-256-sess與SHA-512-256-sess。 - 增加了對 RFC 7616 使用者名稱雜湊 (
userhash) 的支援,以改善隱私保護。
以下範例顯示如何從舊版配置遷移到符合 RFC 7616 的 API:
現有的配置仍可繼續運作,無需變更。然而,對於新應用程式,建議:
- 使用安全的演算法,例如
SHA-512-256或SHA-256。 - 更新
digestProvider以使用新的algorithms參數。 - 除非為了與舊版用戶端相容,否則請避免使用基於
MD5的演算法。
如需完整指南,請參閱 Ktor 伺服器中的摘要驗證。
自訂提供者中的掛起 (Suspending) .authenticate() 多載
自訂驗證提供者 現在可以實作掛起 (suspending) 版本的 DynamicProviderConfig.authenticate() 函式。.authenticate() 函式接受一個掛起 lambda,因此您可以在驗證過程中直接呼叫協同程式 API:
install(Authentication) {
provider("custom") {
authenticate { context ->
delay(10.milliseconds)
context.principal(null)
}
}
}根配置 (Root configuration) data class 對應
ApplicationConfig 現在提供 .getAs() 函式,用於將整個配置反序列化為一個 data class。
以前,反序列化僅限於單個屬性,需要透過 .property() 函式進行存取。有了根級別的支援,您可以將完整的配置結構直接對應到單個 data class:
必要的請求參數輔助函式
Ktor 3.5.0 引入了一組新的擴充函式,簡化了從 ApplicationCall 存取必要請求資料的操作。
以前,驗證必要的請求資料通常需要重複的 null 檢查和標籤返回 (labeled returns)。為了改進此工作流程,Ktor 現在提供以下新的擴充函式:
ApplicationCall.requireQueryParameter()— 從請求 URL 中檢索必要的查詢參數。如果參數缺失,則拋出例外。ApplicationCall.requireHeader()— 檢索必要的 HTTP 標頭值。如果請求中不存在該標頭,則拋出例外。ApplicationCall.requireCookie()— 檢索必要的 Cookie 值,並可選擇使用指定的編碼對其進行解碼。如果 Cookie 缺失,則拋出例外。RoutingCall.requirePathParameter()— 從路由定義中檢索必要的路徑參數。如果比對的路由中不存在該參數,則拋出例外。
每個函式都會傳回一個非 null 值,如果值缺失,則會拋出 MissingRequestParameterException。
ktor-network 的 ES 模組相容性
我們修復了在啟用 ES 模組時無法使用 ktor-network 及其所有相依模組的問題。
為了幫助防止未來發生迴歸 (regression),我們的 JavaScript 測試基礎結構現在預設同時針對 ES2015 和 ES 模組。
有關 Kotlin/JS 模組系統和 ES2015 支援的更多資訊,請參閱:
工作階段 (Sessions) 外掛程式中改進的工作階段管理
Ktor 3.5.0 改進了 工作階段 (Sessions) 外掛程式中的工作階段處理,增加了新的配置選項,讓您能更精確地控制工作階段生命週期、身分識別產生以及網路行為。
僅在修改時傳送工作階段資料
您現在可以將工作階段配置為僅在資料發生變化時才傳送。對於基於 Cookie 的工作階段,這意味著 Set-Cookie 標頭僅在修改時傳送。此最佳化同時適用於基於 Cookie 和標頭的工作階段。
預設情況下,工作階段資料會在每次回應時傳送以保留現有行為。若要僅在修改時傳送,請在工作階段 Cookie 配置中啟用 sendOnlyIfModified 選項:
install(Sessions) {
cookie<MySession>("SESSION") {
sendOnlyIfModified = true
}
}透過請求資料產生工作階段 ID
CookieIdSessionBuilder.identity() 函式現在接受一個 ApplicationCall,允許工作階段 ID 衍生自當前的應用程式呼叫。這支援了諸如將工作階段綁定到已驗證使用者或請求元資料的使用案例。
install(Sessions) {
cookie<UserSession>("user_session", storage = RedisSessionStorage()) {
identity { call ->
call.principal<UserIdPrincipal>()?.name ?: generateSessionId()
}
}
}先前的 identity() 函式已被棄用,建議改用這個具備呼叫感知 (call-aware) 能力的多載版本。
依 ID 清除工作階段
您現在可以透過工作階段的存儲 ID 來使該工作階段失效,而無需作用中的呼叫,這可以透過 call.sessions.clear<UserSession>() 和 CurrentSession.clear() 輔助函式來達成。這兩個函式都會委派給 SessionTrackerById.clearById()。
post("/logout/{sessionId}") {
val sessionId = call.requirePathParameter("sessionId")
call.sessions.clear<UserSession>(sessionId)
call.respond(HttpStatusCode.OK)
}這對於諸如登出使用者的所有裝置,或從背景工作 (background jobs) 中使工作階段過期等情境非常有用。
自訂 SSE 心跳事件
本次發布為 Ktor 伺服器端的 SSE 支援引入了一個新選項,讓您可以使用事件提供者函式 (event provider function) 完整自訂心跳事件:
heartbeat {
period = 30.milliseconds
eventProvider = { ServerSentEvent(data = "ts=${Clock.System.now()}") }
}這使得定期傳送自訂心跳承載資料 (heartbeat payloads) 成為可能,例如時間戳記和狀態資訊。
Jetty 引擎中的 SNI 驗證配置
本次發布為 Jetty 引擎引入了一個新的 secureRequestCustomizer 配置選項,讓您可以直接存取 Jetty 的 SecureRequestCustomizer 執行個體。
這允許您自訂 HTTPS 請求處理,包括伺服器名稱指示 (SNI) 驗證行為。例如,當使用自訂主機對應或自我簽署憑證進行本機測試時,您可以停用 SNI 主機檢查和 SNI 需求:
embeddedServer(
Jetty,
configure = {
secureRequestCustomizer = {
isSniHostCheck = false
isSniRequired = false
}
}
)Ktor Client
OkHttp 與 Apache5 引擎中的自訂 DNS 解析器
Ktor 3.5.0 在 OkHttp 與 Apache5 用戶端引擎中增加了對配置自訂 DNS 解析器的一等支援。
以前,您需要透過存取引擎特定的內部細節來配置自訂 DNS 解析,例如 OkHttp 中的 config {} 或 Apache5 中的 configureConnectionManager { setDnsResolver(...) }。Ktor 現在在每個引擎上公開了專用的配置屬性,以提供一致且型別安全的 API。
OkHttp
您現在可以使用 OkHttpConfig.dns 屬性在 OkHttp 中配置自訂 DNS 解析器:
HttpClient(OkHttp) {
engine {
dns = Dns { hostname -> listOf(InetAddress.getByName("127.0.0.1")) }
}
}如果您未配置 dns 屬性,OkHttp 引擎將繼續使用 OkHttp 預設的 Dns.SYSTEM 解析器。
Apache5
您現在可以使用 Apache5EngineConfig.dnsResolver 屬性在 Apache5 中配置自訂 DNS 解析器:
HttpClient(Apache5) {
engine {
dnsResolver = SystemDefaultDnsResolver.INSTANCE
}
}如果未配置 dnsResolver 屬性,Apache5 引擎將繼續使用 Apache 用戶端預設的 DNS 解析器。
