所以我正在尝试为 Kotlin、Ktor 设置 OAuth。我正在尝试遵循文档 上,但我在step 2的config部分上卡住了。当我的程序运行时:
call.request.queryParameters["redirectUrl"]!!
我得到一个零点例外。在调试器模式下运行程序时,我可以看到 call/request/queryParameters 不为空。所以它应该是不“工作”的“redirectUrl”。
我试图搜索这条线应该做什么,但我无法在任何地方找到它的任何解释。我只能在本文档中找到它的用途。我假设它应该得到一些重定向 URL,但我不知道从哪里来。
我能做些什么来解决我的零点异常?
如果有帮助,这是我的课程
package com.example.plugins
import io.ktor.server.auth.*
import io.ktor.client.*
import io.ktor.client.engine.apache.*
import io.ktor.http.*
import io.ktor.serialization.kotlinx.json.*
import io.ktor.server.sessions.*
import io.ktor.server.response.*
import io.ktor.server.application.*
import io.ktor.server.plugins.contentnegotiation.*
import io.ktor.server.routing.*
fun Application.configureSecurity() {
val redirects = mutableMapOf<String, String>()
authentication {
oauth("auth-oauth-google") {
urlProvider = { "http://localhost:8086/callback" }
providerLookup = {
OAuthServerSettings.OAuth2ServerSettings(
name = "google",
authorizeUrl = "https://accounts.google.com/o/oauth2/auth",
accessTokenUrl = "https://accounts.google.com/o/oauth2/token",
requestMethod = HttpMethod.Post,
clientId = System.getenv("GOOGLE_CLIENT_ID"),
clientSecret = System.getenv("GOOGLE_CLIENT_SECRET"),
defaultScopes = listOf("https://www.googleapis.com/auth/userinfo.profile"),
extraAuthParameters = listOf("access_type" to "offline"),
onStateCreated = { call, state ->
redirects[state] = call.request.queryParameters["redirectUrl"]!!
}
)
}
client = HttpClient(Apache)
}
}
data class MySession(val count: Int = 0)
install(Sessions) {
cookie<MySession>("MY_SESSION") {
cookie.extensions["SameSite"] = "lax"
cookie.maxAgeInSeconds = 120
cookie.path = "/testing"
}
cookie<UserSession>("USER_SESSION") {
cookie.extensions["SameSite"] = "lax"
cookie.maxAgeInSeconds = 120
cookie.path = "/testingss"
}
}
routing {
authenticate("auth-oauth-google") {
get("login") {
call.respondRedirect("/callback")
}
get("/callback") {
val principal: OAuthAccessTokenResponse.OAuth2? = call.principal()
call.sessions.set(UserSession(principal!!.state!!, principal.accessToken))
val redirect = redirects[principal.state!!]
call.respondRedirect(redirect!!)
}
}
get("/session/increment") {
val session = call.sessions.get<MySession>() ?: MySession()
call.sessions.set(session.copy(count = session.count + 1))
call.respondText("Counter is ${session.count}. Refresh to increment.")
}
}
}
如果您需要将客户端重定向到它来自的 URL,请将查询参数
redirectUrl
(实际名称无关紧要,但必须保持一致)添加到 /login
端点。以下是流程的步骤:
/login
,并使用查询参数 redirectUrl
进行响应,其中包含请求的 URL。/login
端点触发OAuth2身份验证,当创建state
时,redirectUrl
被保存到redirects
块内的onStateCreated
地图。举个例子:
get("/{path}") {
val userSession: UserSession? = call.sessions.get()
if (userSession != null) {
val userInfo: UserInfo = httpClient.get("https://www.googleapis.com/oauth2/v2/userinfo") {
headers {
append(HttpHeaders.Authorization, "Bearer ${userSession.token}")
}
}.body()
call.respondText("Hello, ${userInfo.name}!")
} else {
val redirectUrl = URLBuilder("http://0.0.0.0:8080/login").run {
parameters.append("redirectUrl", call.request.uri)
build()
}
call.respondRedirect(redirectUrl)
}
}
我能够通过将
call.request.queryParameters["redirectUrl"]!!
与普通字符串(例如 "http://localhost:3000/home"
)交换来修复它。
只要你只有相同的 url 就可以重定向到。
给出的答案没有解决问题。使用ktor oauth模型示例时出现NullPointerException
另外,在 get("/{path}") {} 块中,对于现有会话可用的情况,我们如何重定向?如果我尝试调用 respondRedirect(),它会再次进入 get("/{path}") {} 块。这是无限循环。