Ktor 中的表单身份验证
Posted
技术标签:
【中文标题】Ktor 中的表单身份验证【英文标题】:Form Authentication in Ktor 【发布时间】:2018-03-12 00:29:21 【问题描述】:我是 Kotlin
和 Ktor
的新手,试图查看身份验证部分,所以我得到了以下代码。
路由“/”和“/bye”工作正常,但路由“登录”给定空白页!
package blog
import kotlinx.html.*
import kotlinx.html.stream.* // for createHTML
import org.jetbrains.ktor.application.*
import org.jetbrains.ktor.auth.*
import org.jetbrains.ktor.features.*
import org.jetbrains.ktor.http.*
import org.jetbrains.ktor.response.*
import org.jetbrains.ktor.routing.*
import org.jetbrains.ktor.request.* // for request.uri
import org.jetbrains.ktor.html.*
import org.jetbrains.ktor.pipeline.*
import org.jetbrains.ktor.host.* // for embededServer
import org.jetbrains.ktor.netty.* // for Netty
fun main(args: Array<String>)
embeddedServer(Netty, 8080, watchPaths = listOf("BlogAppKt"), module = Application::module).start()
fun Application.module()
install(DefaultHeaders)
install(CallLogging)
intercept(ApplicationCallPipeline.Call)
if (call.request.uri == "/hi")
call.respondText("Test String")
install(Routing)
get("/")
call.respondText("""Hello, world!<br><a href="/bye">Say bye?</a>""", ContentType.Text.Html)
get("/bye")
call.respondText("""Good bye! <br><a href="/login">Login?</a> """, ContentType.Text.Html)
route("/login")
authentication
formAuthentication up: UserPasswordCredential ->
when
up.password == "ppp" -> UserIdPrincipal(up.name)
else -> null
handle
val principal = call.authentication.principal<UserIdPrincipal>()
if (principal != null)
call.respondText("Hello, $principal.name")
else
val html = createHTML().html
body
form(action = "/login", encType = FormEncType.applicationXWwwFormUrlEncoded, method = FormMethod.post)
p
+"user:"
textInput(name = "user")
value = principal?.name ?: ""
p
+"password:"
passwordInput(name = "pass")
p
submitInput() value = "Login"
call.respondText(html, ContentType.Text.Html)
当我禁用下面的身份验证部分时,路由'/login'显示所需的表单,这意味着错误最有可能在这部分或调用它的方式上?我猜。
authentication
formAuthentication up: UserPasswordCredential ->
when
up.password == "ppp" -> UserIdPrincipal(up.name)
else -> null
【问题讨论】:
【参考方案1】:您不仅获得了一个空白页面,还获得了401 (UNAUTHORIZED)
的 HTTP 状态代码。那是因为formAuthentication
有四个参数,其中三个具有默认值。你只实现了最后一个(validate
,没有默认):
userParamName: String = "user",
passwordParamName: String = "password",
challenge: FormAuthChallenge = FormAuthChallenge.Unauthorized,
validate: (UserPasswordCredential) -> Principal?
当您到达/login
路由但没有正确的凭据时,您将获得challenge
的默认值,即FormAuthChallenge.Unauthorized
,即401
响应。
您可以使用FormAuthChallenge.Redirect
,而不是使用challenge
的默认值。一个需要两条路线的简短示例:
get("/login")
val html = """
<form action="/authenticate" enctype="..."
REST OF YOUR LOGIN FORM
</form>
"""
call.respondText(html, ContentType.Text.Html)
route("/authenticate")
authentication
formAuthentication(challenge = FormAuthChallenge.Redirect( _, _ -> "/login" ))
credential: UserPasswordCredential ->
when
credential.password == "secret" -> UserIdPrincipal(credential.name)
else -> null
handle
val principal = call.authentication.principal<UserIdPrincipal>()
val html = "Hello, $principal?.name"
call.respondText(html, ContentType.Text.Html)
更新
如果上述方法效果不佳,请清楚地定义userid-parameter
和password-parameter
,因为它们出现在执行POST
的form
中,如下所示:
authentication
formAuthentication("user", "pass",
challenge = FormAuthChallenge.Redirect( _, _ -> "/login" ))
credential: UserPasswordCredential ->
when
credential.password == "secret" -> UserIdPrincipal(credential.name)
else -> null
【讨论】:
给出Status 302
并继续重新加载\login
页面,无论输入密码:(
当我使用formAuthentication("user", "pass", ..
时效果很好,非常感谢。以上是关于Ktor 中的表单身份验证的主要内容,如果未能解决你的问题,请参考以下文章
来自 UserHashedTableAuth 的 Ktor 基本身份验证
Firebase 身份验证不适用于 AppEngine 上的 Ktor 应用程序
基本身份验证应在邮递员中响应 500(授权),但 401 Unauthorized 可以正常工作。使用 ktor intellij mongodb