环境
- workbuddy-switch
0.1.46(Windows x64,桌面版)
- WorkBuddy
5.6(国内版)
- 账号由「导入本机账号」获得(未先做 OAuth 扫码)
现象
账号卡片下方直接显示原始 HTML:
<html>
<head><title>401 Authorization Required</title></head>
<body>
<center><h1>401 Authorization Required</h1></center>
<hr><center>openresty</center>
<p><em>Powered by <a href="https://apisix.apache.org/">APISIX</a>.</em></p></body>
</html>
签到、积分统计、Token 统计、旅行全部失败。
~/.wb-switch/notifications.json 中记录:
Token 刷新失败:<account-id>:需重新登录(缺少 refresh token,无法刷新,需重新登录)
原因
crates/wb-switch-core/src/modules/account.rs:278:
pub fn build_auth_headers(account: &Value) -> HashMap<String, String> {
let mut headers = HashMap::new();
headers.insert(
"Authorization".to_string(),
format!("Bearer {}", get_str(account, "access_token").unwrap_or_default()),
);
// ...
}
get_str 只接受字符串。WorkBuddy 5.6 起 accessToken 是加密信封对象 {$wbEncrypted, envelope},get_str 返回 None,unwrap_or_default() 兜底成空串,实际发出的请求头是:
网关(openresty / APISIX)按无效凭据返回 401,并返回一段 HTML 错误页;这段 HTML 又被原样写进 official_usage_cache.json / travel_cache.json 并展示到界面上。
同一原因也会让刷新链路被静默跳过 —— credits.rs:375 的 authenticated_post:
if is_unauthorized(&response)
&& !working_account
.get("refresh_token")
.and_then(|value| value.as_str())
.unwrap_or("")
.is_empty()
refresh_token 为信封对象时 as_str() 为 None,条件恒为 false,不会触发刷新。
PR #75 已经覆盖了白屏(React #31)/ import-local 400 / 明文被信封覆盖,但「账号库中只有信封凭据」这条路径没有处理。
建议
build_auth_headers(或调用方)在 access_token 为信封形态时提前返回可读错误,例如「该账号凭据为 WorkBuddy 加密态,无法直接用于 API 请求,请使用 OAuth 扫码添加该账号」,而不是发出空 Bearer;
- 错误展示层对 HTML 响应做归一化(提取
<title> 或截断首行),不要把整段 HTML 塞进通知与界面卡片;
- 可考虑在「导入本机账号」检测到信封凭据时,于 UI 上标注该账号仅用于切换,签到 / 积分 / Token 统计需扫码添加明文凭据。
规避方式
删除该账号后改用「OAuth 扫码添加」,凭据为明文,全部功能恢复正常。account.rs:212 的保护逻辑会阻止后续自动 importLocal 用信封覆盖明文,因此不会再退化。
环境
0.1.46(Windows x64,桌面版)5.6(国内版)现象
账号卡片下方直接显示原始 HTML:
签到、积分统计、Token 统计、旅行全部失败。
~/.wb-switch/notifications.json中记录:原因
crates/wb-switch-core/src/modules/account.rs:278:get_str只接受字符串。WorkBuddy 5.6 起accessToken是加密信封对象{$wbEncrypted, envelope},get_str返回None,unwrap_or_default()兜底成空串,实际发出的请求头是:网关(openresty / APISIX)按无效凭据返回 401,并返回一段 HTML 错误页;这段 HTML 又被原样写进
official_usage_cache.json/travel_cache.json并展示到界面上。同一原因也会让刷新链路被静默跳过 ——
credits.rs:375的authenticated_post:refresh_token为信封对象时as_str()为None,条件恒为 false,不会触发刷新。PR #75 已经覆盖了白屏(React #31)/
import-local400 / 明文被信封覆盖,但「账号库中只有信封凭据」这条路径没有处理。建议
build_auth_headers(或调用方)在access_token为信封形态时提前返回可读错误,例如「该账号凭据为 WorkBuddy 加密态,无法直接用于 API 请求,请使用 OAuth 扫码添加该账号」,而不是发出空 Bearer;<title>或截断首行),不要把整段 HTML 塞进通知与界面卡片;规避方式
删除该账号后改用「OAuth 扫码添加」,凭据为明文,全部功能恢复正常。
account.rs:212的保护逻辑会阻止后续自动importLocal用信封覆盖明文,因此不会再退化。