Ktor сессия не найдена - PullRequest
1 голос
/ 21 июня 2020

Я бился головой об стену, пытаясь понять, что здесь не так. Я создал простой сервер Ktor, который позволяет вам создать пользователя, который должен вернуть токен пользователю и сохранить сеанс. Затем я хочу, чтобы конечная точка с проверкой подлинности позволяла удалить пользователя. Однако аутентифицированный вызов загружает пустой сеанс и не может найти пользователя, поэтому его нельзя удалить. Любая помощь будет оценена по достоинству! Код здесь:

Application.kt

...
fun main(args: Array<String>): Unit = io.ktor.server.netty.EngineMain.main(args)

@Suppress("unused") 
@kotlin.jvm.JvmOverloads
fun Application.module(testing: Boolean = false) {
    install(Locations) {
    }

    install(Sessions) {
        cookie<MySession>("MY_SESSION") {
            cookie.extensions["SameSite"] = "lax"
        }
    }

    DatabaseFactory.init()
    val db = MyRepository()
    val jwtService = JwtService()
    val hashFunction = { s: String -> hash(s) }

    install(Authentication) {
        jwt("jwt") { //1
            verifier(jwtService.verifier) // 2
            realm = "My Server"
            validate { // 3
                val payload = it.payload
                val claim = payload.getClaim("id")
                val claimString = claim.asInt()
                val user = db.findUser(claimString) // 4
                user
            }
        }
    }

    install(ContentNegotiation) {
        gson {
        }
    }

    routing {
        users(db, jwtService, hashFunction)
    }
}

UserRoute.kt

...
const val USERS = "$API_VERSION/users"
const val USER_CREATE = "$USERS/create"
const val USER_DELETE = "$USERS/delete"

@KtorExperimentalLocationsAPI
@Location(USER_CREATE)
class UserCreateRoute

@KtorExperimentalLocationsAPI
@Location(USER_DELETE)
class UserDeleteRoute

@KtorExperimentalLocationsAPI
fun Route.users(
    db: Repository,
    jwtService: JwtService,
    hashFunction: (String) -> String
) {
    post<UserCreateRoute> {
        val request = call.receive<CreateUserRequest>()
        val password = request.password
            ?: return@post call.respond(
                HttpStatusCode.Unauthorized, "Missing Fields")
        val email = request.email
            ?: return@post call.respond(
                HttpStatusCode.Unauthorized, "Missing Fields")
        val hash = hashFunction(password)
        try {
            val newUser = db.addUser(email, hash)
            newUser?.userId?.let {
                call.sessions.set(MySession(it))
                call.respondText(
                    jwtService.generateToken(newUser),
                    status = HttpStatusCode.Created
                )
            }
        } catch (e: Throwable) {
            call.respond(HttpStatusCode.BadRequest, "Problems creating User")
        }
    }
   
    authenticate("jwt") {
        delete<UserDeleteRoute> {
            try {
                val userId = call.sessions.get<MySession>()?.userId

                if (userId == null) {
                    call.respond(
                        HttpStatusCode.BadRequest, "Problem retrieving User")
                    return@delete
                }

                if (db.deleteUser(userId)) {
                    call.respond(HttpStatusCode.NoContent, "User deleted")
                } else {
                    call.respond(HttpStatusCode.BadRequest, "Failed to delete user")
                }
            } catch (e: Exception) {
                application.log.error("Failed to delete user")
                call.respond(HttpStatusCode.BadRequest, "Failed to delete user")
            }
        }
    }
}

Есть что-то, что я ' м пропал? Токен успешно возвращен, а затем мой запрос на удаление направляется в нужное место, но строка val userId = call.sessions.get<MySession>()?.userId каждый раз возвращает null.

1 Ответ

0 голосов
/ 23 июля 2020

Вы не показываете клиентский код, но это не менее важно. Вероятно, проблема в клиенте, а не на сервере. Когда клиенты выполняют удаление, отправляет ли он токен?

jwt будет более сложным для basi c auth после того, как вы получите сеанс, каждый запрос должен включать заголовок сеанса:

curl  -H "MY_SESSION: f152dad6e955ba53" -D - localhost:8080/api/admin/principle
...