feat: 添加小程序 web-view Token 传递问题分析与修复方案,更新 H5 端 URL 验证逻辑
This commit is contained in:
@@ -10,6 +10,22 @@
|
||||
|
||||
<body>
|
||||
<script>window.__INITIAL_URL__ = document.URL;</script>
|
||||
<!-- 🐞 原始 URL 验证 -->
|
||||
<div id="url-check" style="display:none" data-url=""></div>
|
||||
<script>
|
||||
var u = document.URL;
|
||||
document.getElementById('url-check').setAttribute('data-url', u);
|
||||
console.log('[URL_CHECK] document.URL:', u);
|
||||
console.log('[URL_CHECK] search:', location.search);
|
||||
console.log('[URL_CHECK] has_token:', location.search.includes('token='));
|
||||
// 如果没 token,在页面顶部写一行红色提示
|
||||
if (!location.search.includes('token=')) {
|
||||
var d = document.createElement('div');
|
||||
d.style.cssText = 'position:fixed;top:0;left:0;right:0;z-index:99999;background:red;color:white;padding:10px;font-size:14px;text-align:center';
|
||||
d.textContent = '⚠️ URL无token: search=[' + location.search + '] url=' + u.substring(0, 80);
|
||||
document.body.prepend(d);
|
||||
}
|
||||
</script>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/main.tsx"></script>
|
||||
</body>
|
||||
|
||||
@@ -61,7 +61,10 @@ export function LoginPage() {
|
||||
const navigate = useNavigate();
|
||||
const { setTokenAndUser, fetchProfile } = useUser();
|
||||
const [error, setError] = useState("");
|
||||
const [debug] = useState<DebugInfo>(() => ({ ...INIT_DEBUG }));
|
||||
const [debug] = useState<DebugInfo>(() => {
|
||||
sessionStorage.setItem('debug', '1');
|
||||
return { ...INIT_DEBUG };
|
||||
});
|
||||
|
||||
// ─── 🐞 调试更新函数 ───
|
||||
const dbg = (patch: Partial<DebugInfo>) => {
|
||||
@@ -80,7 +83,18 @@ export function LoginPage() {
|
||||
|
||||
// 优先使用 URL 中的 token(小程序传参)
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
const tokenFromUrl = params.get('token');
|
||||
let tokenFromUrl = params.get('token');
|
||||
|
||||
// 兜底:从 hash 读取(微信 web-view 可能丢 query 但 hash 安全)
|
||||
if (!tokenFromUrl) {
|
||||
const hash = window.location.hash;
|
||||
if (hash.startsWith('#token=')) {
|
||||
tokenFromUrl = decodeURIComponent(hash.replace('#token=', ''));
|
||||
// ─── 🐞 ───
|
||||
dbg({ step: "token-from-hash", tokenPrefix: tokenFromUrl.substring(0, 30) + "..." });
|
||||
// ─── 🐞 ───
|
||||
}
|
||||
}
|
||||
|
||||
// ─── 🐞 ───
|
||||
dbg({ step: "check-url-token", hasTokenParam: !!tokenFromUrl, tokenPrefix: tokenFromUrl ? tokenFromUrl.substring(0, 30) + "..." : "" });
|
||||
@@ -118,7 +132,8 @@ export function LoginPage() {
|
||||
// ─── 🐞 ───
|
||||
dbg({ step: "fetch-ok", fetchError: `is_onboarded=${dto?.is_onboarded}` });
|
||||
// ─── 🐞 ───
|
||||
navigate(dto?.is_onboarded ? "/home" : "/onboarding", { replace: true });
|
||||
const target = dto?.is_onboarded ? "/home" : "/onboarding";
|
||||
navigate(sessionStorage.getItem('debug') ? target + "?debug=1" : target, { replace: true });
|
||||
}).catch((e: any) => {
|
||||
// ─── 🐞 ───
|
||||
dbg({ step: "fetch-fail", fetchError: `${e?.message || e}` });
|
||||
@@ -151,7 +166,8 @@ export function LoginPage() {
|
||||
phone: res.mobile,
|
||||
});
|
||||
fetchProfile().then((dto) => {
|
||||
navigate(dto?.is_onboarded ? "/home" : "/onboarding", { replace: true });
|
||||
const target = dto?.is_onboarded ? "/home" : "/onboarding";
|
||||
navigate(sessionStorage.getItem('debug') ? target + "?debug=1" : target, { replace: true });
|
||||
});
|
||||
}).catch((err) => {
|
||||
dbg({ step: "dev-login-fail", devLoginError: err?.message || String(err) });
|
||||
|
||||
@@ -64,7 +64,11 @@ export interface TokenPayload {
|
||||
|
||||
/** 解析 JWT payload(base64 解码,不验证签名) */
|
||||
export function decodeToken(token: string): TokenPayload {
|
||||
return JSON.parse(atob(token.split('.')[1]));
|
||||
// JWT 使用 base64url 编码,需转为标准 base64
|
||||
const base64 = token.split('.')[1]
|
||||
.replace(/-/g, '+')
|
||||
.replace(/_/g, '/');
|
||||
return JSON.parse(atob(base64));
|
||||
}
|
||||
|
||||
/** 开发环境:获取测试账号 token */
|
||||
|
||||
Reference in New Issue
Block a user