fix: add User-Agent/Referer headers, GET index first for session cookie, handle non-JSON login response
This commit is contained in:
parent
26ebfe132c
commit
a0a4b5698d
@ -16,9 +16,10 @@ import kotlinx.serialization.json.*
|
||||
* Sage 客户端 - 处理登录、Session 管理和 UI 加载
|
||||
*
|
||||
* Sage 使用 Cookie Session 认证:
|
||||
* 1. POST /rbac/user/userpassword_login.dspy 登录获取 session cookie
|
||||
* 2. 后续请求自动携带 cookie
|
||||
* 3. GET /xxx.ui 获取 JSON 格式的 UI 描述
|
||||
* 1. GET 首页获取初始 session cookie
|
||||
* 2. POST /rbac/user/userpassword_login.dspy 登录
|
||||
* 3. 后续请求自动携带 cookie
|
||||
* 4. GET /xxx.ui 获取 JSON 格式的 UI 描述
|
||||
*/
|
||||
class SageClient {
|
||||
|
||||
@ -54,45 +55,55 @@ class SageClient {
|
||||
suspend fun login(username: String, password: String): Boolean = mutex.withLock {
|
||||
_loginError.value = null
|
||||
try {
|
||||
// Step 1: GET the index page to obtain initial session cookies
|
||||
// Sage requires a valid session cookie before accepting login POST
|
||||
val indexResponse = client.get("$baseUrl/")
|
||||
println("[Sage] GET / status: ${indexResponse.status}")
|
||||
|
||||
// Step 2: POST login
|
||||
val url = "$baseUrl/rbac/user/userpassword_login.dspy"
|
||||
val encodedUser = java.net.URLEncoder.encode(username, "UTF-8")
|
||||
val encodedPass = java.net.URLEncoder.encode(password, "UTF-8")
|
||||
val formBody = "username=$encodedUser&passwd=$encodedPass"
|
||||
|
||||
val response = client.post(url) {
|
||||
header(HttpHeaders.UserAgent, "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36")
|
||||
header(HttpHeaders.Referrer, "$baseUrl/")
|
||||
contentType(ContentType.Application.FormUrlEncoded)
|
||||
setBody(formBody)
|
||||
}
|
||||
|
||||
val body = response.bodyAsText()
|
||||
println("[Sage] Login response status: ${response.status}")
|
||||
println("[Sage] Login response body: ${body.take(200)}")
|
||||
println("[Sage] Login response body: ${body.take(300)}")
|
||||
|
||||
// Check if response is JSON
|
||||
if (!body.trimStart().startsWith("{")) {
|
||||
// Non-JSON response - likely an error page or auth failure
|
||||
if (response.status.value == 401 || response.status.value == 403) {
|
||||
_loginError.value = "登录失败: 服务器拒绝请求 (${response.status.value})"
|
||||
} else {
|
||||
_loginError.value = "登录失败: 服务器返回非JSON响应 (${response.status.value})"
|
||||
}
|
||||
println("[Sage] Non-JSON login response: ${body.take(200)}")
|
||||
return@withLock false
|
||||
}
|
||||
|
||||
// Sage 返回 UiMessage 格式: {"widgettype": "Message", "options": {...}}
|
||||
// 或者返回错误: {"widgettype": "Error", "options": {...}}
|
||||
val json = try {
|
||||
Json.parseToJsonElement(body).jsonObject
|
||||
} catch (e: Exception) {
|
||||
_loginError.value = "登录响应格式错误: ${e.message}"
|
||||
_loginError.value = "登录响应解析错误: ${e.message}"
|
||||
return@withLock false
|
||||
}
|
||||
|
||||
val widgetType = json["widgettype"]?.jsonPrimitive?.content
|
||||
|
||||
if (widgetType == "Message" || widgetType == "UiMessage") {
|
||||
// 检查是否有 session cookie
|
||||
val cookies = cookieStorage.get(URLBuilder(baseUrl).build())
|
||||
if (cookies.isNotEmpty()) {
|
||||
println("[Sage] Login successful, got ${cookies.size} cookies")
|
||||
_isLoggedIn.value = true
|
||||
true
|
||||
} else {
|
||||
// 即使没有 cookie,如果服务器返回成功也算登录成功
|
||||
// 有些部署可能使用 token 而非 cookie
|
||||
println("[Sage] Login successful (no cookies)")
|
||||
_isLoggedIn.value = true
|
||||
true
|
||||
}
|
||||
println("[Sage] Login successful, cookies: ${cookies.size}")
|
||||
_isLoggedIn.value = true
|
||||
true
|
||||
} else {
|
||||
// 错误消息
|
||||
val options = json["options"]?.jsonObject ?: JsonObject(emptyMap())
|
||||
@ -118,7 +129,9 @@ class SageClient {
|
||||
val url = if (path.startsWith("http")) path else "$baseUrl/${path.trimStart('/')}"
|
||||
println("[Sage] Fetching UI: $url")
|
||||
|
||||
val response = client.get(url)
|
||||
val response = client.get(url) {
|
||||
header(HttpHeaders.UserAgent, "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36")
|
||||
}
|
||||
val body = response.bodyAsText()
|
||||
|
||||
if (!response.status.isSuccess()) {
|
||||
@ -151,6 +164,7 @@ class SageClient {
|
||||
url {
|
||||
params.forEach { (k, v) -> parameters.append(k, v) }
|
||||
}
|
||||
header(HttpHeaders.UserAgent, "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36")
|
||||
when {
|
||||
jsonBody != null -> {
|
||||
contentType(ContentType.Application.Json)
|
||||
@ -169,6 +183,7 @@ class SageClient {
|
||||
url {
|
||||
params.forEach { (k, v) -> parameters.append(k, v) }
|
||||
}
|
||||
header(HttpHeaders.UserAgent, "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user