Ktor封装authenticate到自定义Route扩展时Principal解析失败问题及类型安全认证实现诉求
Ktor封装authenticate到自定义Route扩展时Principal解析失败问题及类型安全认证实现诉求
我现在在做Ktor的类型安全认证封装,遇到了一个头疼的问题:把authenticate封装到自定义Route扩展函数里之后,principal总是返回null,但直接写的话就正常。先给大家说下具体情况:
问题复现
我有个示例项目,其中/private路由正常工作,但/private-2路由里的principal始终为null。你可以通过这个命令跑测试看到问题:
./gradlew test --info
我的诉求
我想给Ktor的Authentication插件做一个类型安全的封装,避免重构时出现认证配置和Principal类型不匹配的问题。期望能写出这样的代码:
routing { requiredAuth { // <-- *保证这里的Principal类型和认证配置匹配* get("/secure") { val user = call.authenticatedUser() // <-- *直接返回非空的UserPrincipal* call.respond("Hello, ${user.name}") } } }
当前进展(以及哪里出问题了)
步骤1:基础Scope实现(正常工作)
先做了一个带Principal访问的Scope类,直接用的话没问题:
class AuthTypeSafeScope { fun ApplicationCall.authenticatedUser() = principal<UserPrincipal>() ?: error("Not authenticated") }
步骤2:手动使用(正常工作)
直接嵌套authenticate和Scope的话,principal能正常解析:
authenticate("user-header") { AuthTypeSafeScope().apply { get("/test") { val user = call.authenticatedUser() // *能成功拿到Principal* call.respond(user.name) } } }
步骤3:封装成扩展函数(失败)
但把逻辑封装到Route扩展函数里之后,principal就一直返回null了:
inline fun Route.requiredAuth(crossinline block: AuthTypeSafeScope.() -> Unit) { authenticate("user-header") { AuthTypeSafeScope().apply(block) // <-- *这里的Principal解析为null* } }
症状是代码能编译运行,但principal<UserPrincipal>()始终返回null。
我的疑惑
我怀疑是Route.()和AuthTypeSafeScope.()的Scope处理导致Ktor的Principal解析出问题,但我之前做过类似的Kotlin DSL封装,Scope处理都没问题,所有上层的函数都能正常访问。而且为什么步骤2里Scope的使用方式就没问题呢?有没有大佬能帮我分析下原因,以及怎么正确封装才能保留Principal解析的功能?
内容来源于stack exchange
相关产品推荐
相关产品推荐

