KTOR中表单登录后如何重定向回初始访问页面?
Ktor 登录后重定向回原受保护资源的解决方案
1. 在认证拦截中传递原请求URI到登录页
给auth-session认证添加失败挑战逻辑,将用户原本要访问的URI作为查询参数附加到登录跳转地址,确保登录页能拿到目标地址:
authenticate("auth-session") { get("/list") { // 你的业务逻辑实现 } // 其他受auth-session保护的路由... }.challenge { defaultScheme, realm -> // 获取当前请求的完整URI(包含查询参数) val redirectUri = call.request.uri // 对URI进行URL编码,避免特殊字符解析异常 val encodedUri = java.net.URLEncoder.encode(redirectUri, "UTF-8") // 重定向到登录页并携带原地址参数 call.respondRedirect("/login?redirectUri=$encodedUri") complete() }
2. 登录页接收并保存原地址
修改登录的GET路由,接收redirectUri参数,可选择存入临时session或传递给模板,确保POST登录时能获取到:
方式一:存入临时Session(推荐)
先定义临时存储重定向地址的Session类:
data class TempRedirectSession(val redirectUri: String)
在Session配置中注册这个临时Session:
install(Sessions) { cookie<UserSession>("user_session") cookie<TempRedirectSession>("temp_redirect") // 新增临时Session配置 }
然后修改登录GET路由:
route("/login") { get { val redirectUri = call.request.queryParameters["redirectUri"]?.let { // 解码URL参数 java.net.URLDecoder.decode(it, "UTF-8") } ?: "/" // 将原地址存入临时Session call.sessions.set(TempRedirectSession(redirectUri)) call.respond(FreeMarkerContent("login.ftl", model = null)) } // 后续POST登录逻辑... }
方式二:传递给模板
如果不想用临时Session,可将参数传递给模板,让表单提交时携带:
route("/login") { get { val redirectUri = call.request.queryParameters["redirectUri"]?.let { java.net.URLDecoder.decode(it, "UTF-8") } ?: "/" call.respond(FreeMarkerContent("login.ftl", mapOf("redirectUri" to redirectUri))) } }
同时在login.ftl的表单中添加隐藏字段:
<form method="post"> <!-- 用户名、密码等表单字段 --> <input type="hidden" name="redirectUri" value="${redirectUri}"> <button type="submit">登录</button> </form>
3. 登录成功后重定向到原地址
修改登录POST路由,获取保存的redirectUri,完成登录后跳转至目标地址:
authenticate("auth-form") { post { val loginUser = call.principal<UserIdPrincipal>()?.name.toString() val session = UserSession(loginUser, AccessLevel.USER) call.sessions.set(session) // 获取重定向地址:优先取表单参数(方式二),再取临时Session(方式一),默认跳转到首页 val redirectUri = call.request.formParameters["redirectUri"] ?: call.sessions.get<TempRedirectSession>()?.redirectUri ?: "/" // 清除临时Session(如果用了方式一) call.sessions.clear<TempRedirectSession>() // 重定向到用户原本要访问的资源 call.respondRedirect(redirectUri) } }
内容的提问来源于stack exchange,提问作者Andrey Karpenkov
相关产品推荐
相关产品推荐

