修复第三方登录旧响应覆盖新会话并补充跨标签回归
This commit is contained in:
1 parent
30415593a6
commit
c3467875c6
6 files changed
+484
-25
No files matched your search
@@ -133,6 +133,7 @@ var fe = {
|
||||
W = null,
|
||||
G = null,
|
||||
K = 0,
|
||||
loginAttempt = null,
|
||||
q = null;
|
||||
function J() {
|
||||
W !== null && (clearInterval(W), (W = null));
|
||||
@@ -154,6 +155,8 @@ var fe = {
|
||||
// 只在桌面展示区域申请新二维码,并核对图片、ticket 与 token 的完整性。
|
||||
if (!k.value || L.value) return;
|
||||
let e = ++K;
|
||||
const attempt = C.prepareLogin();
|
||||
loginAttempt = attempt;
|
||||
(Z(),
|
||||
(z.value = ``),
|
||||
(R.value = !1),
|
||||
@@ -165,7 +168,7 @@ var fe = {
|
||||
let t = await E.get(`/mp_weixin_notice/qrcode`, void 0, !1, {
|
||||
timeoutMs: 15e3,
|
||||
});
|
||||
if (e !== K) return;
|
||||
if (e !== K || !attempt.isCurrent()) return;
|
||||
if (
|
||||
typeof t?.img_url != `string` ||
|
||||
!t.img_url ||
|
||||
@@ -177,7 +180,7 @@ var fe = {
|
||||
throw Error(`二维码加载失败,请重新获取`);
|
||||
((I.value = t), (z.value = ``), Ee());
|
||||
} catch (t) {
|
||||
if (e !== K) return;
|
||||
if (e !== K || !attempt.isCurrent()) return;
|
||||
(J(),
|
||||
Y(),
|
||||
(z.value = loginErrorMessage(t, `二维码加载失败,请稍后重试`)));
|
||||
@@ -187,7 +190,7 @@ var fe = {
|
||||
}
|
||||
async function De() {
|
||||
// 同一代次最多一个查询在途;Wait/Success/Expired/SelectClient/WaitBind 分别处理。
|
||||
if (!I.value || q === K) return;
|
||||
if (!I.value || q === K || !loginAttempt?.isCurrent()) return;
|
||||
let e = K,
|
||||
t = I.value;
|
||||
q = e;
|
||||
@@ -203,7 +206,7 @@ var fe = {
|
||||
timeoutMs: 1e4,
|
||||
},
|
||||
);
|
||||
if (e !== K) return;
|
||||
if (e !== K || !loginAttempt.isCurrent()) return;
|
||||
if (!n || typeof n.status != `string`)
|
||||
throw Error(`扫码登录状态异常,请重新获取二维码`);
|
||||
if (n.status === `Wait`) return;
|
||||
@@ -252,7 +255,7 @@ var fe = {
|
||||
}
|
||||
(Z(), (z.value = `扫码登录状态异常,请重新获取二维码`));
|
||||
} catch (t) {
|
||||
if (e !== K) return;
|
||||
if (e !== K || !loginAttempt.isCurrent()) return;
|
||||
(Z(),
|
||||
(z.value = loginErrorMessage(
|
||||
t,
|
||||
@@ -270,6 +273,7 @@ var fe = {
|
||||
(K++,
|
||||
Z(),
|
||||
(I.value = null),
|
||||
(loginAttempt = null),
|
||||
(L.value = !1),
|
||||
(H.value = !1),
|
||||
(R.value = !1),
|
||||
@@ -283,11 +287,13 @@ var fe = {
|
||||
z.value = `登录响应无效,请重新扫码;若持续失败,请联系客服。`;
|
||||
return;
|
||||
}
|
||||
(C.loginWithJwt(e), K++, T.push(auth_redirect_r(w.query.redirect)));
|
||||
(loginAttempt.commit(e),
|
||||
K++,
|
||||
T.push(auth_redirect_r(w.query.redirect)));
|
||||
}
|
||||
async function Oe() {
|
||||
// 多账号扫码只能提交当前返回列表中明确可登录的账号,且请求绑定当前二维码代次。
|
||||
if (H.value) return;
|
||||
if (H.value || !loginAttempt?.isCurrent()) return;
|
||||
if (
|
||||
!I.value ||
|
||||
!B.value.some((e) => e.id === V.value && e.status === 1)
|
||||
@@ -310,12 +316,12 @@ var fe = {
|
||||
timeoutMs: 15e3,
|
||||
},
|
||||
);
|
||||
if (e !== K) return;
|
||||
if (e !== K || !loginAttempt.isCurrent()) return;
|
||||
t?.jwt
|
||||
? $(t.jwt)
|
||||
: (z.value = `登录响应无效,请重新扫码;若持续失败,请联系客服。`);
|
||||
} catch (t) {
|
||||
if (e !== K) return;
|
||||
if (e !== K || !loginAttempt.isCurrent()) return;
|
||||
z.value = loginErrorMessage(t);
|
||||
} finally {
|
||||
e === K && (H.value = !1);
|
||||
@@ -329,6 +335,7 @@ var fe = {
|
||||
await D().catch(() => {}));
|
||||
}),
|
||||
watch(N, Q),
|
||||
watch(() => C.token, Q),
|
||||
onUnmounted(() => {
|
||||
(A?.removeEventListener(`change`, j), Q());
|
||||
}),
|
||||
|
||||
+22
-5
@@ -695,6 +695,22 @@ const useAuth = defineStore("auth", () => {
|
||||
localStorage.setItem("jwt", jwt);
|
||||
}
|
||||
|
||||
// 身份结果只归属于请求开始时的会话;也检查持久凭证,覆盖 storage 事件尚未处理的窗口。
|
||||
function prepareLogin() {
|
||||
const version = sessionVersion;
|
||||
const persistedToken = localStorage.getItem("jwt");
|
||||
const isCurrent = () =>
|
||||
version === sessionVersion &&
|
||||
persistedToken === localStorage.getItem("jwt");
|
||||
return {
|
||||
isCurrent,
|
||||
commit(jwt) {
|
||||
if (!isCurrent()) throw Error("登录状态已变化,请重新发起登录。");
|
||||
loginWithJwt(jwt);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// 旧平台带来的凭证先暂存待验证,不立即写成已登录状态,避免路由守卫误放行。
|
||||
function prepareLegacyLogin(jwt = localStorage.getItem("jwt")) {
|
||||
clear();
|
||||
@@ -726,6 +742,7 @@ const useAuth = defineStore("auth", () => {
|
||||
);
|
||||
}
|
||||
if (session.promise) return session.promise;
|
||||
const loginAttempt = prepareLogin();
|
||||
const apiBase = String(useRuntimeConfig().public.apiBase ?? "");
|
||||
const controller = new AbortController();
|
||||
session.controller = controller;
|
||||
@@ -764,7 +781,7 @@ const useAuth = defineStore("auth", () => {
|
||||
account.id <= 0
|
||||
)
|
||||
throw Error("暂时无法验证登录身份,请稍后重试。");
|
||||
loginWithJwt(session.jwt);
|
||||
loginAttempt.commit(session.jwt);
|
||||
overview.value = account;
|
||||
},
|
||||
15_000,
|
||||
@@ -800,7 +817,7 @@ const useAuth = defineStore("auth", () => {
|
||||
if (type === "code" && account.includes("@"))
|
||||
throw Error("验证码登录仅支持手机号");
|
||||
const api = useApi();
|
||||
const version = sessionVersion;
|
||||
const loginAttempt = prepareLogin();
|
||||
loading.value = true;
|
||||
try {
|
||||
const result = await api.post(
|
||||
@@ -819,11 +836,11 @@ const useAuth = defineStore("auth", () => {
|
||||
false,
|
||||
{ timeoutMs: 15_000 },
|
||||
);
|
||||
if (version !== sessionVersion) throw Error("登录状态已变化,请重试");
|
||||
if (!loginAttempt.isCurrent()) throw Error("登录状态已变化,请重试");
|
||||
ft(result);
|
||||
if (!ut(result?.jwt))
|
||||
throw Error("登录响应无效,请重新登录;若持续失败,请联系客服。");
|
||||
loginWithJwt(result.jwt);
|
||||
loginAttempt.commit(result.jwt);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
@@ -886,7 +903,7 @@ const useAuth = defineStore("auth", () => {
|
||||
loading,
|
||||
isLoggedIn,
|
||||
login,
|
||||
loginWithJwt,
|
||||
prepareLogin,
|
||||
fetchOverview,
|
||||
refreshOverview,
|
||||
logout,
|
||||
|
||||
@@ -119,6 +119,7 @@ var ve = {
|
||||
H = ref(``),
|
||||
U = ref(!1),
|
||||
W = ref(!1),
|
||||
loginAttempt = null,
|
||||
G = !0;
|
||||
onBeforeUnmount(() => {
|
||||
G = !1;
|
||||
@@ -127,6 +128,8 @@ var ve = {
|
||||
async function K() {
|
||||
if (!W.value && G) {
|
||||
((W.value = !0), (U.value = !1), (H.value = ``));
|
||||
const attempt = A.prepareLogin();
|
||||
loginAttempt = attempt;
|
||||
try {
|
||||
if (N) {
|
||||
if (!P) throw Error(`扫码会话已过期,请返回登录重新扫码`);
|
||||
@@ -134,10 +137,10 @@ var ve = {
|
||||
ticket: P.ticket,
|
||||
token: P.token,
|
||||
});
|
||||
if (!G) return;
|
||||
if (!G || !attempt.isCurrent()) return;
|
||||
if (e.status === `Success` && isValidJwt(e.jwt)) {
|
||||
(wechat_binding_t(sessionStorage),
|
||||
A.loginWithJwt(e.jwt),
|
||||
attempt.commit(e.jwt),
|
||||
await navigateTo(F));
|
||||
return;
|
||||
}
|
||||
@@ -147,7 +150,7 @@ var ve = {
|
||||
return;
|
||||
}
|
||||
let t = await S.get(`/oauth/token`);
|
||||
if (!G) return;
|
||||
if (!G || !attempt.isCurrent()) return;
|
||||
let n = oauth_n(
|
||||
t,
|
||||
window.location.origin,
|
||||
@@ -159,7 +162,7 @@ var ve = {
|
||||
).origin,
|
||||
);
|
||||
if (n.kind === `login`) {
|
||||
(A.loginWithJwt(n.jwt), await navigateTo(`/`));
|
||||
(attempt.commit(n.jwt), await navigateTo(`/`));
|
||||
return;
|
||||
}
|
||||
if (n.kind !== `bind`)
|
||||
@@ -167,6 +170,7 @@ var ve = {
|
||||
U.value = !0;
|
||||
} catch (e) {
|
||||
G &&
|
||||
attempt.isCurrent() &&
|
||||
(H.value = e instanceof Error ? e.message : `验证授权会话失败`);
|
||||
} finally {
|
||||
G && (W.value = !1);
|
||||
@@ -210,7 +214,8 @@ var ve = {
|
||||
// 必须先验证授权会话并同意协议;提交验证码绑定,微信额外携带扫码 ticket/token,成功响应的 JWT 合法后才建立会话。
|
||||
async function Le() {
|
||||
if (!V.value && G) {
|
||||
if (((H.value = ``), !U.value)) {
|
||||
if (((H.value = ``), !U.value || !loginAttempt.isCurrent())) {
|
||||
U.value = !1;
|
||||
H.value = `请先验证授权会话;会话失效时请返回登录重新授权`;
|
||||
return;
|
||||
}
|
||||
@@ -223,6 +228,7 @@ var ve = {
|
||||
return;
|
||||
}
|
||||
V.value = !0;
|
||||
const attempt = loginAttempt;
|
||||
try {
|
||||
let e = q.validationError?.();
|
||||
if (e) throw Error(e);
|
||||
@@ -244,14 +250,15 @@ var ve = {
|
||||
: {}),
|
||||
},
|
||||
);
|
||||
if (!G) return;
|
||||
if (!G || !attempt.isCurrent()) return;
|
||||
if (!isValidJwt(t?.jwt))
|
||||
throw Error(`绑定会话已失效,请返回登录后重新发起第三方授权`);
|
||||
(N && wechat_binding_t(sessionStorage),
|
||||
A.loginWithJwt(t.jwt),
|
||||
attempt.commit(t.jwt),
|
||||
await navigateTo(F));
|
||||
} catch (e) {
|
||||
G &&
|
||||
attempt.isCurrent() &&
|
||||
((H.value =
|
||||
e instanceof Error ? e.message : `绑定失败,请重试`),
|
||||
await q.handleError?.(e));
|
||||
|
||||
@@ -54,9 +54,10 @@ var w = {
|
||||
async function A() {
|
||||
if (k && !D.value) {
|
||||
((D.value = !0), (O.value = ``));
|
||||
const loginAttempt = E.prepareLogin();
|
||||
try {
|
||||
let t = await T.get(`/oauth/token`);
|
||||
if (!k) return;
|
||||
if (!k || !loginAttempt.isCurrent()) return;
|
||||
let n = oauth_n(
|
||||
t,
|
||||
window.location.origin,
|
||||
@@ -68,7 +69,7 @@ var w = {
|
||||
).origin,
|
||||
);
|
||||
if (n.kind === `login`) {
|
||||
E.loginWithJwt(n.jwt);
|
||||
loginAttempt.commit(n.jwt);
|
||||
try {
|
||||
sessionStorage.removeItem(`console-oauth-pending`);
|
||||
} catch {}
|
||||
@@ -79,7 +80,9 @@ var w = {
|
||||
window.location.replace(n.url);
|
||||
} else throw Error(`授权会话已过期,请返回登录并重新授权`);
|
||||
} catch (e) {
|
||||
k && (O.value = e instanceof Error ? e.message : `恢复登录失败`);
|
||||
k &&
|
||||
loginAttempt.isCurrent() &&
|
||||
(O.value = e instanceof Error ? e.message : `恢复登录失败`);
|
||||
} finally {
|
||||
k && (D.value = !1);
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ export default defineNuxtPlugin({
|
||||
// Read the latest value: several storage events may already be queued.
|
||||
const persisted = localStorage.getItem("jwt");
|
||||
if (persisted === auth.token) return;
|
||||
if (isValidJwt(persisted)) auth.loginWithJwt(persisted);
|
||||
if (isValidJwt(persisted)) auth.prepareLogin().commit(persisted);
|
||||
else auth.clear();
|
||||
const route = router.currentRoute.value;
|
||||
if (!auth.isLoggedIn && !isPublicRoute(route)) {
|
||||
|
||||
Reference in new issue
Block a user