Ktor:如何在路由处理程序中检查身份验证?
Ktor: How to check authentication inside a route handler?
我正在使用 ktor v0.9.2,我想根据用户是否经过身份验证为同一路由发送不同的内容。
我遇到的问题是我无法访问 authenticate { }
块之外的主体。
我的设置是这样的:
data class User(
val userId: Int
) : io.ktor.auth.Principal
fun Application.myApp() {
install(Authentication) {
jwt {
verifier(JwtConfig.verifier)
validate { credential ->
val userId = credential.payload.getClaim("userId").asInt()
when {
userId > 0 -> User(userId)
else -> null
}
}
}
}
install(DefaultHeaders)
install(CallLogging)
install(ContentNegotiation) {
jackson { }
}
install(Routing) {
authenticate {
get("/protected") {
// This works fine!!
val user = call.authentication.principal<User>()
call.respond(user)
}
}
get("/") {
val user = call.authentication.principal<User>() // -> User is always null here
if (user == null) {
call.respondText("Not Logged User")
} else {
call.respondText("Logged User")
}
}
}
}
/protected
路由工作正常,但在 /
路由中主体始终为空。我认为这是一些管道问题,但我有点迷路。有人可以提供一些见解吗?谢谢!
您使用的是什么版本的 ktor?
你能告诉我们你的身份验证设置吗?
你应该有这样的东西(0.9.2):
install(Authentication) {
jwt {
verifier(JwtConfig.verifier)
realm = JwtConfig.realm
validate {
val email = it.payload.getClaim("email").toString()
userRepository.findUser(email)?.let { user ->
val token = JwtConfig.makeToken(user)
user.copy(token = token)
}
}
}
}
如果身份验证过程成功,用户将可以通过主体访问。
这是 0.9.3 的更新代码。
从验证行为的测试开始。
只需添加 optional
标志。
class KtorTest {
@Test fun server() {
withTestApplication({ myApp() }) {
val userId = 918354853
val token = JwtConfig.makeToken(User(userId))
// The protected route
handleRequest {
uri = "/protected"
addHeader("Authorization", "Bearer $token")
}.let {
it.requestHandled shouldBe true
it.response.content.shouldNotBeNullOrBlank() shouldContain userId.toString()
}
// Optional route without token
handleRequest {}.let {
it.requestHandled shouldBe true
it.response.content.shouldNotBeNullOrBlank() shouldBeEqualTo "Not Logged User"
}
// Optional route with token
handleRequest {
addHeader("Authorization", "Bearer $token")
}.let {
it.requestHandled shouldBe true
it.response.content.shouldNotBeNullOrBlank() shouldBeEqualTo "Logged User"
}
}
}
}
data class User(val userId: Int) : Principal
fun Application.myApp() {
install(Authentication) {
jwt {
verifier(JwtConfig.verifier)
validate { credential ->
val userId = credential.payload.getClaim("userId").asInt()
when {
userId > 0 -> User(userId)
else -> null
}
}
}
}
install(DefaultHeaders)
install(CallLogging)
install(ContentNegotiation) { jackson { } }
install(Routing) {
authenticate {
get("/protected") {
// This works fine!!
val user = call.authentication.principal<User>()!!
call.respond(user)
}
}
authenticate(optional = true) {
get("/") {
val user = call.authentication.principal<User>() // -> User is always null here
if (user == null) {
call.respondText("Not Logged User")
} else {
call.respondText("Logged User")
}
}
}
}
}
我正在使用 ktor v0.9.2,我想根据用户是否经过身份验证为同一路由发送不同的内容。
我遇到的问题是我无法访问 authenticate { }
块之外的主体。
我的设置是这样的:
data class User(
val userId: Int
) : io.ktor.auth.Principal
fun Application.myApp() {
install(Authentication) {
jwt {
verifier(JwtConfig.verifier)
validate { credential ->
val userId = credential.payload.getClaim("userId").asInt()
when {
userId > 0 -> User(userId)
else -> null
}
}
}
}
install(DefaultHeaders)
install(CallLogging)
install(ContentNegotiation) {
jackson { }
}
install(Routing) {
authenticate {
get("/protected") {
// This works fine!!
val user = call.authentication.principal<User>()
call.respond(user)
}
}
get("/") {
val user = call.authentication.principal<User>() // -> User is always null here
if (user == null) {
call.respondText("Not Logged User")
} else {
call.respondText("Logged User")
}
}
}
}
/protected
路由工作正常,但在 /
路由中主体始终为空。我认为这是一些管道问题,但我有点迷路。有人可以提供一些见解吗?谢谢!
您使用的是什么版本的 ktor? 你能告诉我们你的身份验证设置吗?
你应该有这样的东西(0.9.2):
install(Authentication) {
jwt {
verifier(JwtConfig.verifier)
realm = JwtConfig.realm
validate {
val email = it.payload.getClaim("email").toString()
userRepository.findUser(email)?.let { user ->
val token = JwtConfig.makeToken(user)
user.copy(token = token)
}
}
}
}
如果身份验证过程成功,用户将可以通过主体访问。
这是 0.9.3 的更新代码。
从验证行为的测试开始。
只需添加 optional
标志。
class KtorTest {
@Test fun server() {
withTestApplication({ myApp() }) {
val userId = 918354853
val token = JwtConfig.makeToken(User(userId))
// The protected route
handleRequest {
uri = "/protected"
addHeader("Authorization", "Bearer $token")
}.let {
it.requestHandled shouldBe true
it.response.content.shouldNotBeNullOrBlank() shouldContain userId.toString()
}
// Optional route without token
handleRequest {}.let {
it.requestHandled shouldBe true
it.response.content.shouldNotBeNullOrBlank() shouldBeEqualTo "Not Logged User"
}
// Optional route with token
handleRequest {
addHeader("Authorization", "Bearer $token")
}.let {
it.requestHandled shouldBe true
it.response.content.shouldNotBeNullOrBlank() shouldBeEqualTo "Logged User"
}
}
}
}
data class User(val userId: Int) : Principal
fun Application.myApp() {
install(Authentication) {
jwt {
verifier(JwtConfig.verifier)
validate { credential ->
val userId = credential.payload.getClaim("userId").asInt()
when {
userId > 0 -> User(userId)
else -> null
}
}
}
}
install(DefaultHeaders)
install(CallLogging)
install(ContentNegotiation) { jackson { } }
install(Routing) {
authenticate {
get("/protected") {
// This works fine!!
val user = call.authentication.principal<User>()!!
call.respond(user)
}
}
authenticate(optional = true) {
get("/") {
val user = call.authentication.principal<User>() // -> User is always null here
if (user == null) {
call.respondText("Not Logged User")
} else {
call.respondText("Logged User")
}
}
}
}
}