fix(auth): harden WeChat login and explicit identity switching
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
/* Browser identity is a random credential, never a fingerprint or a report. */
|
||||
window.AccountClient = (function () {
|
||||
'use strict';
|
||||
var key = 'juzi.identity.v1', user = null;
|
||||
function read() { try { return localStorage.getItem(key); } catch (_) { return null; } }
|
||||
var key = 'juzi.identity.v1', kindKey = 'juzi.auth.kind.v1', user = null;
|
||||
function read(name) { try { return localStorage.getItem(name || key); } catch (_) { return null; } }
|
||||
function rememberKind() { try { if (user) localStorage.setItem(kindKey, user.kind); } catch (_) {} }
|
||||
function request(url, data) {
|
||||
return fetch(url, { credentials: 'same-origin', method: data ? 'POST' : 'GET',
|
||||
headers: data ? { 'Content-Type': 'application/json' } : {},
|
||||
@@ -13,13 +14,16 @@ window.AccountClient = (function () {
|
||||
function browser(consent) {
|
||||
return request('api/auth/browser', { consent: consent, token: read() }).then(function (v) {
|
||||
try { localStorage.setItem(key, v.token); } catch (_) { /* session cookie still works */ }
|
||||
user = v.user; return v;
|
||||
user = v.user; rememberKind(); return v;
|
||||
});
|
||||
}
|
||||
function init() {
|
||||
function init(options) {
|
||||
return request('api/auth/session').then(function (v) {
|
||||
user = v.user;
|
||||
if (!user && read()) return browser(true).catch(function (e) {
|
||||
rememberKind();
|
||||
// A missing WeChat session is not permission to switch to a browser account.
|
||||
// OAuth returns must also stay explicit when its cookie was not retained.
|
||||
if (!user && !(options && options.restoreBrowser === false) && read(kindKey) !== 'wechat' && read()) return browser(true).catch(function (e) {
|
||||
// Do not replace an existing credential on a transient server/network error.
|
||||
if (/身份已失效/.test(e.message)) { try { localStorage.removeItem(key); } catch (_) {} }
|
||||
throw e;
|
||||
|
||||
+30
-7
@@ -1304,7 +1304,13 @@
|
||||
startCamera(); // 复用启停与预热(camSeqCam 防竞态)
|
||||
},
|
||||
'history': function () { openHistory(); },
|
||||
'history-retry': function () { renderHistoryList(); }
|
||||
'history-retry': function () { renderHistoryList(); },
|
||||
'switch-login': function () {
|
||||
historySeq++;
|
||||
$('#login-consent').checked = false;
|
||||
$('#login-message').textContent = '微信与本机浏览器为独立账号,报告不会自动合并。请选择登录方式;返回可保留当前登录。';
|
||||
showScreen('s-login', 'push');
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('click', function (e) {
|
||||
@@ -1427,14 +1433,31 @@
|
||||
history.replaceState({ screen: 's-login' }, ''); // 刷新后从启动页开始,历史栈的屏标记与之对齐
|
||||
renderCamStep();
|
||||
if (!(/[?&]mock=1/.test(location.search) && /[?&]screen=report/.test(location.search))) {
|
||||
var loginError = /[?&]login_error=([^&#]*)/.exec(location.search);
|
||||
var loginSuccess = /[?&]login=success(?:&|$)/.test(location.search);
|
||||
var oauthReturn = !!loginError || loginSuccess;
|
||||
loginBusy = true;
|
||||
AccountClient.init().then(function () {
|
||||
if (AccountClient.user()) showScreen('s-splash', 'replace');
|
||||
else $('#login-message').textContent = /[?&]login_error=/.test(location.search)
|
||||
? '微信登录未完成,可重试或使用本机浏览器登录。'
|
||||
: '本机登录仅限当前浏览器,不支持换手机找回。';
|
||||
AccountClient.init({ restoreBrowser: !oauthReturn }).then(function () {
|
||||
if (loginError) {
|
||||
var code = loginError[1];
|
||||
$('#login-message').textContent = code === 'state'
|
||||
? '登录链接已过期或会话丢失,请在同一微信窗口重新点击微信登录。'
|
||||
: code === 'network' ? '暂时无法连接微信服务,请稍后重新登录。'
|
||||
: '微信授权未完成,请重试;如仍失败,请将错误页面截图发给管理员。也可选择本机浏览器登录。';
|
||||
} else if (loginSuccess && (!AccountClient.user() || AccountClient.user().kind !== 'wechat')) {
|
||||
$('#login-message').textContent = '微信返回后登录会话未能保存,请在同一微信窗口重新登录。';
|
||||
} else if (AccountClient.user()) showScreen('s-splash', 'replace');
|
||||
else $('#login-message').textContent = '微信登录可跨手机查看报告;本机登录仅限当前浏览器。';
|
||||
}).catch(function (e) { $('#login-message').textContent = e.message; })
|
||||
.finally(function () { loginBusy = false; });
|
||||
.finally(function () {
|
||||
loginBusy = false;
|
||||
if (oauthReturn) {
|
||||
var clean = new URL(location.href);
|
||||
clean.searchParams.delete('login'); clean.searchParams.delete('login_error');
|
||||
if (clean.hash === '#wechat_redirect') clean.hash = '';
|
||||
history.replaceState(history.state, '', clean.pathname + clean.search + clean.hash);
|
||||
}
|
||||
});
|
||||
}
|
||||
// 仅调试用:?mock=1&screen=report 直渲 mock 报告页(供无头浏览器截图验证布局,非正式入口)
|
||||
// 有 MOCK_FIXTURE 时走 fixture(检测可视化同步出图),否则回退 SkinScore 内置样本
|
||||
|
||||
Reference in New Issue
Block a user