#kotlin #vert.x
#kotlin #vert.x
Вопрос:
Я настроил JDBCAuth с помощью vert.x, и аутентификация работает. Я получаю объект пользователя после JDBCAuth.authenticate (adminLoginHandler), но он равен нулю в RoutingContext при следующем HTTP-запросе GET (adminReadHandler).
Я проверил, RoutingContext там содержит объект session и cookie.
Я добавляю BodyHandler, CookieHandler, SessionHandler.create(LocalSessionStore.create(vertx)), UserSessionHandler.create(adminAuth) перед установкой маршрутов.
Я использую OpenAPI3RouterFactory для настройки маршрутизации.
Я думаю, я сделал все, как в документации и примере кода. Чего я не понимаю?
suspend fun createJDBCAuth(vertx : Vertx, name : String) : JDBCAuth
{
val con = getConnection(vertx, name)
return JDBCAuth.create(vertx, con)
.setAuthenticationQuery("SELECT PASSWORD, PASSWORD_SALT FROM "user" WHERE USERNAME = ?")
.setHashStrategy(JDBCHashStrategy.createPBKDF2(vertx))
.setNonces(json {
array(45, 385)
})
}
adminAuth = createJDBCAuth(vertx, "adminreader")
OpenAPI3RouterFactory.create(vertx, "openapi.yaml")
{ ar ->
if (ar.succeeded())
{
// Spec loaded with success
var factory = ar.result()
logger.info("Factory succeed")
factory.setBodyHandler(BodyHandler.create().setBodyLimit(1024 * 1024))
.addGlobalHandler(CookieHandler.create())
.addGlobalHandler(SessionHandler.create(LocalSessionStore.create(vertx)))
.addGlobalHandler(UserSessionHandler.create(adminAuth))
.addGlobalHandler(CorsHandler.create("https://localhost:3000")
.allowCredentials(true)
.allowedHeader("Content-Type")
.allowedMethod(HttpMethod.GET)
.allowedMethod(HttpMethod.POST)
.allowedMethod(HttpMethod.OPTIONS)
)
inputMap.forEach { path ->
when {
path.key == "/admin/login" -> factory.addHandlerByOperationId(path.value.operationId, adminLoginHandler)
path.key.startsWith("/admin/") -> factory.addHandlerByOperationId(path.value.operationId, adminReadHandler)
}
}
Обновлена функция.
private val adminLoginHandler = Handler<RoutingContext>
{ rc ->
adminAuth.authenticate(rc.bodyAsJson)
{ res ->
launch {
var retJson = json { obj() }
if (res.succeeded()) {
var user = res.result()
rc.session()?.regenerateId()
rc.setUser(user)
retJson = retJson.put("succeed", true)
if (user.isAuthorizedAwait("createadmin"))
retJson = retJson.put("createadmin", true)
} else {
retJson = retJson
.put("succeed", false)
.put("message", res.cause().message)
}
rc.response()
.putHeader("content-type", "application/json")
.end(retJson.encode())
}
}
}
private val adminReadHandler = Handler<RoutingContext>
{ rc ->
if (rc.user() == null)
rc.response().setStatusCode(403).end()
else
{
val user = rc.user()
val principal = user.principal()
}
}
Комментарии:
1. Когда вы вручную реализуете обработчик аутентификации, после аутентификации вы должны вручную задать пользователю vertx.io/docs/apidocs/io/vertx/ext/web/… Добавить
rc.user = user
в adminLoginHandler2. Я изменил adminLoginHandler (обновленный код в вопросе), и rc.setUser (пользователь) добавляет объект JDBCUser в rc, но все равно при следующем запросе GET объект rc.user равен null. Я вижу один объект rc.cookies с ключом «vertx-web.session», но я не вижу никаких файлов cookie в chrome debugger.
3. Я создал рабочий пример, высмеивающий поставщика авторизации и удаляющий фабрику маршрутизаторов openapi, вы можете это проверить? gist.github.com/slinkydeveloper /…
4.
UserSessionHandler
Должен выполнить трюк по сохранению пользователя в сеансе и его извлечению. Вы уверены, что файл cookie отправляется обратно на сервер?5. Нет, я не видел никаких файлов cookie в моей реализации.
Ответ №1:
Оказалось, что проблема была не на стороне серверной части (vertx). Я использую API выборки браузера в коде интерфейса и забыл включить учетные данные: параметр «включить».
Франческо: Спасибо вам за ваши усилия. Ваша суть помогла мне проследить проблему по частям.
P.s.: хотя мой authn / authz сейчас работает, я все еще не вижу файлы cookie на панели network / cookies отладчика chrome, использующего fetch api. Если я записываю URL-адрес непосредственно в браузер, я вижу все.