Ktor中的表单身份验证 [英] Form Authentication in Ktor

查看:198
本文介绍了Ktor中的表单身份验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是KotlinKtor的新手,试图查看身份验证部分,因此获得了以下代码.

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-parameterpassword-parameter,它们出现在执行POSTform中,如下所示:

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆