Contents

Web 应用的“按需登录”与“意图回跳”

第一步:记录意图

在组件中,我们不再直接跳转,而是先过一遍“安检”。

// KbCard.vue
const openChat = () => {
  const targetUrl = `/chat?kb=${props.id}`;
  // 调用通用的检查登录方法,并告诉它:登录完我想去 targetUrl
  if (userStore.checkLogin({ message: "请先登录", redirectUrl: targetUrl })) {
    router.push(targetUrl);
  }
};

第二步:持久化存储

因为登录通常涉及跨页面跳转(如跳转到 SSO 统一认证平台),我们需要把这个“意图”存入浏览器的 sessionStorage

// userStore.js
const initUser = (forceRedirect, customRedirect) => {
  if (forceRedirect) {
    // 将相对路径补全为绝对路径,确跳转绝对准确
    const redirectUrl = customRedirect || window.location.href;
    sessionStorage.setItem("redirectUrl", redirectUrl); // 存入“小本本”

    // 跳转 SSO 登录页
    window.location.href = `SSO_URL...`;
  }
};

第三步:认证回调

用户登录成功,SSO 会把用户送回我们的网站,并带上 Token。此时页面会重新加载。

第四步:意图还原

在路由跳转前,我们翻开“小本本”,看看有没有还没完成的愿望。

// router/index.js
router.beforeEach((to, from, next) => {
  const token = to.query.AccessToken;
  if (token) {
    // 1. 翻看小本本
    const redirectUrl = sessionStorage.getItem("redirectUrl");
    if (redirectUrl) {
      sessionStorage.removeItem("redirectUrl"); // 读完就撕掉,防止重复跳转

      const url = new URL(redirectUrl);
      const targetPath = url.pathname;
      const query = Object.fromEntries(new URLSearchParams(url.search));

      // 2. 净化 URL,剔除认证相关的参数
      delete query.AccessToken;

      // 3. 无感回跳到目标页面
      next({ path: targetPath, query, replace: true });
      return;
    }
  }
  next();
});