Ktor中的表单身份验证 [英] Form Authentication in Ktor
问题描述
我是Kotlin
和Ktor
的新手,试图查看身份验证部分,因此获得了以下代码.
I'm new to Kotlin
and Ktor
trying to see the authentication part, so I got the below code.
路线"/"和"/bye"工作正常,但路线登录"显示为空白页!
Routes "/" and "/bye" are working fine, but route "login" given blank page!
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"显示了所需的表格,这意味着该部分或调用方式中最有可能出现错误?我想.
When I disabled the authentication part below, the route '/login' displayed the required form, which means the error is most likely in this part or in the way of calling it? I guess.
authentication {
formAuthentication { up: UserPasswordCredential ->
when {
up.password == "ppp" -> UserIdPrincipal(up.name)
else -> null
}
}
}
推荐答案
您不会简单地获得空白页,而是获得HTTP状态码401 (UNAUTHORIZED)
.这是因为formAuthentication
具有四个参数,其中三个具有默认值.您仅实现了最后一个(validate
,没有默认值):
You're not simply given a blank page, you get a HTTP status code of 401 (UNAUTHORIZED)
. That's because formAuthentication
has four parameters, three of them with defaults. You only implemented the last one (validate
, without default):
userParamName: String = "user",
passwordParamName: String = "password",
challenge: FormAuthChallenge = FormAuthChallenge.Unauthorized,
validate: (UserPasswordCredential) -> Principal?
只要在没有适当凭据的情况下到达/login
路由,就会得到challenge
的默认值,即FormAuthChallenge.Unauthorized
,这是401
的响应.
Whenever you reach the /login
route without the right credentials already in place, you get the default for challenge
, which is FormAuthChallenge.Unauthorized
, which is a 401
response.
您可以使用FormAuthChallenge.Redirect
,而不是使用challenge
的默认值.一个简短的示例,它需要两条路线:
Instead of using the default for challenge
, you could use a FormAuthChallenge.Redirect
. A short example that requires two routes:
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
中,如下所示:
In case the above did not work well, define both the userid-parameter
and password-parameter
clearly as they appear in the form
that do the POST
, as below:
authentication {
formAuthentication("user", "pass",
challenge = FormAuthChallenge.Redirect({ _, _ -> "/login" })){
credential: UserPasswordCredential ->
when {
credential.password == "secret" -> UserIdPrincipal(credential.name)
else -> null
}
}
}
这篇关于Ktor中的表单身份验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!