控制Ktor 0.9.0 servlet中的cookie生命周期

时间:2017-11-14 16:40:29

标签: web-applications kotlin ktor

我在删除Ktor 0.9.0服务器端应用程序设置的cookie时遇到问题。也许我不知道如何以正确的方式去做,或者在Ktor框架中有遗漏。

Cookie的创建和删除本身并不是问题,但为了删除cookie,我将使用与客户端浏览器上的cookie一起存储的相同路径。 Ktor让我通过cookie创建来控制路径。这是我的配置:

install(Sessions) {
    cookie<MySession>(sessionMarker) {
        cookie.duration = cookieDuration
        cookie.path = "/myWebapp"
        transform(SessionTransportTransformerMessageAuthentication(sessionKey))
    }
}

在登录页面/myWebapp/page/login上,我创建了一个cookie,然后将其发送到客户端,它会来回传输发送到Web应用程序的其他请求:

call.sessions.set(MySession([some data class arguments]))

Cookie会在客户端上检查时显示路径/myWebapp。默认值为/myWebapp/page,因为这是登录页面的路径,但路径来自上面显示的cookie配置。到目前为止一直很好。

最终用户想要通过POST请求注销登录页面:

call.sessions.clear<MySession>()

这里的问题是我没有找到控制cookie路径的方法。由于登录页面/myWebapp/page/login正在将过期的Cookie发送回客户端以获取其他路径(其自己的/myWebapp/page),因此原始Cookie不会被删除(/myWebapp/page!= /myWebapp )。

如何在尝试删除时,如何在Ktor 0.9.0中控制cookie的路径?

我知道如何解决它:通过从我删除它的路径创建cookie。但这不是我想要的(像/myWebapp/others这样的Web应用程序中的其他路径应该使用cookie)。能够在创建过程中控制cookie的路径是没有意义的。

1 个答案:

答案 0 :(得分:1)

我认为您可以尝试创建自己的自定义SessionTransportCookie。

如果您更深入地了解方法cookie<MySession>(sessionMarker),您会找到以下代码:

inline fun <reified S : Any> Sessions.Configuration.cookie(name: String, block: CookieSessionBuilder<S>.() -> Unit): Unit = cookie(name, S::class, block)

inline fun <S : Any> Sessions.Configuration.cookie(name: String, sessionType: KClass<S>, block: CookieSessionBuilder<S>.() -> Unit) {
    val builder = CookieSessionBuilder(sessionType).apply(block)
    val transport = SessionTransportCookie(name, builder.cookie, builder.transformers)
    val tracker = SessionTrackerByValue(sessionType, builder.serializer)
    val provider = SessionProvider(name, sessionType, transport, tracker)
    register(provider)
}

此处的重要一行是按行创建会话传输Cookie:SessionTransportCookie(name, builder.cookie, builder.transformers)

让我们更深入地了解SessionTransportCookie

class SessionTransportCookie(val name: String,
                             val configuration: CookieConfiguration,
                             val transformers: List<SessionTransportTransformer>
) : SessionTransport {

    override fun receive(call: ApplicationCall): String? {
        return transformers.transformRead(call.request.cookies[name])
    }

    override fun send(call: ApplicationCall, value: String) {
        val now = LocalDateTime.now()
        val expires = now.plus(configuration.duration)
        val maxAge = configuration.duration[ChronoUnit.SECONDS].toInt()
        val cookie = Cookie(name,
                transformers.transformWrite(value),
                configuration.encoding,
                maxAge,
                expires,
                configuration.domain,
                configuration.path,
                configuration.secure,
                configuration.httpOnly,
                configuration.extensions
        )

        call.response.cookies.append(cookie)
    }

    override fun clear(call: ApplicationCall) {
        call.response.cookies.appendExpired(name)
    }
}

class CookieConfiguration {
    var duration: TemporalAmount = Duration.ofDays(7)
    var encoding: CookieEncoding = CookieEncoding.URI_ENCODING
    var domain: String? = null
    var path: String? = null
    var secure: Boolean = false
    var httpOnly: Boolean = false
    val extensions: MutableMap<String, String?> = mutableMapOf()
}

因此,如您所见,在本课程中,您可以自定义Cookie send/clear逻辑。