vue2不同用户在一个浏览器登录互不影响

实现方式:
核心原理 Session Storage 隔离:
核心机制:Session Storage + Cookie 前缀隔离
使用 sessionStorage 存储当前会话用户标识和 token,每个标签页独立
Cookie 前缀隔离:使用 user_{username}_ 前缀为每个用户单独存储记住密码信息
Token 隔离存储:将每个用户的 token 以 token_{username} 为键存储在 sessionStorage 中

工作流程
1.用户在标签页A登录用户A,在标签页B登录用户B
2.每个标签页的 sessionStorage 中存储各自的 currentSessionUser 标识
3.每个用户的 token 以用户名为键分别存储
4.Cookie 中每个用户的记住密码信息也以用户名为前缀存储
5.这样实现了同一浏览器中多个标签页可以登录不同用户且互不干扰
这个实现方案确保了在同一浏览器中可以同时登录多个不同账户,每个标签页维护自己的会话状态,不会相互影响。

1.修改登录逻辑

 //login.vue
 handleLogin() {
      this.$refs.loginForm.validate((valid) => {
        if (valid) {
          this.loading = true;

          // 使用用户名作为键前缀存储记住密码信息
          const userPrefix = `user_${this.loginForm.username}_`;
          if (this.loginForm.rememberMe) {
            Cookies.set(userPrefix + "username", this.loginForm.username, {
              expires: 30,
            });
            Cookies.set(
              userPrefix + "password",
              encrypt(this.loginForm.password),
              { expires: 30 }
            );
            Cookies.set(userPrefix + "rememberMe", this.loginForm.rememberMe, {
              expires: 30,
            });
          } else {
            Cookies.remove(userPrefix + "username");
            Cookies.remove(userPrefix + "password");
            Cookies.remove(userPrefix + "rememberMe");
          }

          // 正常调用登录,但保存会话信息
          this.$store
            .dispatch("Login", this.loginForm)
            .then((res) => {
              console.log("登录成功", res);
              // 登录成功后设置当前会话标识
              sessionStorage.setItem(
                "currentSessionUser",
                this.loginForm.username
              );

              // 确保token已经保存到sessionStorage
              if (res && res.token) {
                sessionStorage.setItem(
                  `token_${this.loginForm.username}`,
                  res.token
                );
              }

              // 使用setTimeout确保DOM更新完成后再跳转
              setTimeout(() => {
                this.$router
                  .push({ path: this.redirect || "/" })
                  .then(() => {
                    console.log("路由跳转成功");
                  })
                  .catch((err) => {
                    console.error("路由跳转失败:", err);
                  });
              }, 100);
            })
            .catch((error) => {
              console.error("登录失败:", error);
              this.loading = false;
              if (this.captchaOnOff) {
                this.getCode();
              }
            });
        }
      });
    },

2.获取cookie逻辑

 getCookie() {
      // 获取当前会话用户(如果存在)
      const currentSessionUser = sessionStorage.getItem("currentSessionUser");

      if (currentSessionUser) {
        // 如果有当前会话用户,优先使用该用户的记住密码信息
        const userPrefix = `user_${currentSessionUser}_`;
        const username = Cookies.get(userPrefix + "username");
        const password = Cookies.get(userPrefix + "password");
        const rememberMe = Cookies.get(userPrefix + "rememberMe");

        this.loginForm = {
          username: username === undefined ? this.loginForm.username : username,
          password:
            password === undefined
              ? this.loginForm.password
              : decrypt(password),
          rememberMe: rememberMe === undefined ? false : Boolean(rememberMe),
        };
      } else {
        // 查找任意用户的记住密码信息
        const allCookies = Cookies.get();
        for (const key in allCookies) {
          if (key.startsWith("user_") && key.endsWith("_username")) {
            const userPrefix = key.replace("username", "");
            const username = Cookies.get(userPrefix + "username");
            const password = Cookies.get(userPrefix + "password");
            const rememberMe = Cookies.get(userPrefix + "rememberMe");

            this.loginForm = {
              username: username || this.loginForm.username,
              password: password ? decrypt(password) : this.loginForm.password,
              rememberMe: rememberMe ? Boolean(rememberMe) : false,
            };
            break;
          }
        }
      }
    },

3.修改 Vuex Store 中的 Login Action


// store/modules/user.js 或类似文件
const user = {
  state: {
    token: getToken(), // 使用我们修改后的getToken函数
    name: "",
    avatar: "",
    id: "",
    nick: "",
    roles: [],
    permissions: [],
    unreadCount: 0, //消息未读数据
  },

// 登录
Login({ commit }, userInfo) {
  const { username, password, code, uuid } = userInfo;
  return new Promise((resolve, reject) => {
    login(username, password, code, uuid).then(res => {
      // 设置token到store和sessionStorage
      commit('SET_TOKEN', res.token);
      // 同时保存到sessionStorage实现会话隔离
      sessionStorage.setItem(`token_${username}`, res.token);
      resolve(res);
    }).catch(error => {
      reject(error);
    });
  });
},

 // 退出系统
LogOut({ commit, state }) {
  return new Promise((resolve, reject) => {
    logout(state.token)
      .then(() => {
        commit("SET_TOKEN", "");
        commit("SET_ROLES", []);
        commit("SET_PERMISSIONS", []);
        removeToken();
        // 清除当前会话标识
        sessionStorage.removeItem('currentSessionUser');
        resolve();
      })
      .catch((error) => {
        reject(error);
      });
  });
},

// 前端 登出
FedLogOut({ commit }) {
  return new Promise((resolve) => {
    commit("SET_TOKEN", "");
    removeToken();
    // 清除当前会话标识
    sessionStorage.removeItem('currentSessionUser');
    resolve();
  });
}

4.修改 utils/auth.js 中的 Token 管理函数

// 如果该文件不存在,请创建此文件
// utils/auth.js 或类似文件
const TokenKey = 'Admin-Token';

// 获取当前有效的token
export function getToken() {
  // 首先尝试从sessionStorage获取当前用户的token
  const currentUser = sessionStorage.getItem('currentSessionUser');
  if (currentUser) {
    const userToken = sessionStorage.getItem(`token_${currentUser}`);
    if (userToken) {
      return userToken;
    }
  }
  
  // 回退到localStorage或cookies
  return localStorage.getItem(TokenKey) || '';
}

// 设置token
export function setToken(token) {
  const currentUser = sessionStorage.getItem('currentSessionUser');
  if (currentUser) {
    // 保存到sessionStorage实现标签页隔离
    sessionStorage.setItem(`token_${currentUser}`, token);
  } else {
    // 默认保存方式
    localStorage.setItem(TokenKey, token);
  }
}

// 移除token
export function removeToken() {
  const currentUser = sessionStorage.getItem('currentSessionUser');
  if (currentUser) {
    sessionStorage.removeItem(`token_${currentUser}`);
  } else {
    localStorage.removeItem(TokenKey);
  }
  sessionStorage.removeItem('currentSessionUser');
}```

5.在应用初始化时恢复会话,

//在 src/main.js 或 src/App.vue 的 created 钩子中添加:
import store from '@/store'; 

created() {
    // 应用初始化时确保token正确设置
    const currentUser = sessionStorage.getItem("currentSessionUser");
    if (currentUser) {
      const token = sessionStorage.getItem(`token_${currentUser}`);
      if (token) {
        store.commit("SET_TOKEN", token);
      }
    }
  },
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值