最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Vue3 登錄狀態(tài)持久化方案詳解(Token 是什么)

 更新時間:2026年02月04日 10:37:49   作者:前端開發(fā)_穆金秋  
本文給大家介紹Vue3登錄狀態(tài)持久化方案詳解包括Token 是什么的相關知識,本文結合實例代碼給大家介紹的非常詳細,感興趣的朋友跟隨小編一起看看吧

Vue3中登錄狀態(tài)刷新后消失的原因在于內(nèi)存數(shù)據(jù)重置。

解決方案包括:

  1. 使用localStorage存儲token和用戶信息;
  2. 通過Pinia持久化插件自動保存狀態(tài);
  3. 組合式API封裝認證邏輯;
  4. 配合路由守衛(wèi)控制訪問權限;
  5. 使用Cookie支持SSR。

最佳實踐建議采用雙重存儲策略(Vuex+localStorage+sessionStorage),并注意安全性和自動刷新token機制。

根據(jù)項目需求(SPA/SSR/安全級別)選擇合適的持久化方案。

token 通常是 JWT(JSON Web Token)格式的字符串

Vue3登錄狀態(tài)持久化方案

為什么刷新后登錄狀態(tài)會消失?

在 Vue3 項目中,登錄狀態(tài)通常保存在內(nèi)存中(如 Vuex/Pinia 的狀態(tài)、組件的響應式數(shù)據(jù))。當頁面刷新時:

  • 內(nèi)存數(shù)據(jù)被清空 - 瀏覽器重新加載頁面,JavaScript 環(huán)境重置
  • Vue 應用重新初始化 - store 和組件狀態(tài)恢復為初始值
  • HTTP 請求是無狀態(tài)的 - 服務器不會自動記住客戶端狀態(tài)

如何持久化登錄狀態(tài)

方案一:Token + localStorage(最常用)

// 1. 登錄成功后保存 token
import { ref } from 'vue'
const login = async () => {
  const response = await api.login(username, password)
  if (response.success) {
    // 保存到 localStorage
    localStorage.setItem('token', response.data.token)
    localStorage.setItem('userInfo', JSON.stringify(response.data.user))
    // 同時保存到 Vue 狀態(tài)管理
    userStore.setUser(response.data.user)
    userStore.setToken(response.data.token)
  }
}
// 2. 應用初始化時恢復狀態(tài)
import { onMounted } from 'vue'
import { useUserStore } from '@/stores/user'
const userStore = useUserStore()
onMounted(() => {
  // 從 localStorage 恢復
  const token = localStorage.getItem('token')
  const userInfo = localStorage.getItem('userInfo')
  if (token && userInfo) {
    userStore.setToken(token)
    userStore.setUser(JSON.parse(userInfo))
  }
})

方案二:使用 Vuex/Pinia 持久化插件

安裝 pinia-plugin-persistedstate

npm install pinia-plugin-persistedstate

配置:

// main.js / main.ts
import { createPinia } from 'pinia'
import { createPersistedState } from 'pinia-plugin-persistedstate'
const pinia = createPinia()
pinia.use(createPersistedState({
  storage: localStorage,
  // 或使用 sessionStorage
  // storage: sessionStorage,
  // 自定義序列化(可選)
  serializer: {
    serialize: JSON.stringify,
    deserialize: JSON.parse,
  },
  // 自動恢復所有 store
  auto: true
}))
app.use(pinia)

使用:

// stores/user.js
import { defineStore } from 'pinia'
export const useUserStore = defineStore('user', {
  state: () => ({
    token: '',
    userInfo: null
  }),
  actions: {
    login(data) {
      this.token = data.token
      this.userInfo = data.user
    },
    logout() {
      this.token = ''
      this.userInfo = null
    }
  },
  // 啟用持久化
  persist: {
    key: 'user', // 存儲的 key
    storage: localStorage,
    paths: ['token', 'userInfo'] // 只持久化這些字段
  }
})

方案三:組合式 API 封裝

// composables/useAuth.js
import { ref, onMounted } from 'vue'
import { useRouter } from 'vue-router'
export function useAuth() {
  const token = ref('')
  const user = ref(null)
  const router = useRouter()
  // 登錄
  const login = async (credentials) => {
    const response = await api.login(credentials)
    setAuth(response.data)
  }
  // 設置認證信息
  const setAuth = (data) => {
    token.value = data.token
    user.value = data.user
    // 保存到 localStorage
    localStorage.setItem('auth_token', data.token)
    localStorage.setItem('auth_user', JSON.stringify(data.user))
    // 設置 axios 默認請求頭
    api.setAuthToken(data.token)
  }
  // 登出
  const logout = () => {
    token.value = ''
    user.value = null
    localStorage.removeItem('auth_token')
    localStorage.removeItem('auth_user')
    api.clearAuthToken()
    router.push('/login')
  }
  // 初始化檢查登錄狀態(tài)
  const initAuth = () => {
    const savedToken = localStorage.getItem('auth_token')
    const savedUser = localStorage.getItem('auth_user')
    if (savedToken && savedUser) {
      token.value = savedToken
      user.value = JSON.parse(savedUser)
      api.setAuthToken(savedToken)
    }
  }
  // 檢查是否已登錄
  const isAuthenticated = () => {
    return !!token.value
  }
  return {
    token,
    user,
    login,
    logout,
    initAuth,
    isAuthenticated
  }
}

方案四:配合路由守衛(wèi)

// router/index.js
import { createRouter, createWebHistory } from 'vue-router'
const routes = [
  {
    path: '/dashboard',
    component: () => import('@/views/Dashboard.vue'),
    meta: { requiresAuth: true }
  },
  {
    path: '/login',
    component: () => import('@/views/Login.vue'),
    meta: { guestOnly: true }
  }
]
const router = createRouter({
  history: createWebHistory(),
  routes
})
// 路由守衛(wèi)
router.beforeEach((to, from, next) => {
  const token = localStorage.getItem('token')
  // 需要認證的頁面
  if (to.meta.requiresAuth && !token) {
    next('/login')
    return
  }
  // 僅游客可訪問的頁面(如登錄頁)
  if (to.meta.guestOnly && token) {
    next('/dashboard')
    return
  }
  next()
})

方案五:使用 Cookie(服務端渲染友好)

// 使用 js-cookie 庫
import Cookies from 'js-cookie'
// 保存 token
Cookies.set('token', response.data.token, { 
  expires: 7, // 7天后過期
  secure: true, // HTTPS only
  sameSite: 'strict'
})
// 讀取 token
const token = Cookies.get('token')

最佳實踐建議

雙重存儲策略

// 同時使用多種存儲方式
const saveAuth = (data) => {
  // 1. Vuex/Pinia
  store.setAuth(data)
  // 2. localStorage(主要持久化)
  localStorage.setItem('auth', JSON.stringify(data))
  // 3. sessionStorage(標簽頁內(nèi)有效)
  sessionStorage.setItem('auth_temp', JSON.stringify(data))
  // 4. Cookie(SSR 需要)
  Cookies.set('token', data.token, { expires: 7 })
}

安全考慮

import CryptoJS from 'crypto-js'
const encryptData = (data) => {
  return CryptoJS.AES.encrypt(
    JSON.stringify(data), 
    'your-secret-key'
  ).toString()
}
  • 對于敏感信息,考慮使用 sessionStorage(標簽頁關閉即清除)
  • 或者使用加密存儲:npm install crypto-js

自動刷新 Token

// 定期刷新 token
setInterval(async () => {
  if (isAuthenticated()) {
    const newToken = await api.refreshToken()
    localStorage.setItem('token', newToken)
  }
}, 30 * 60 * 1000) // 每30分鐘

選擇哪種方案取決于你的具體需求:

  • 純 SPA 應用:localStorage + Pinia 持久化插件
  • 需要 SSR:Cookie + 服務端狀態(tài)同步
  • 高安全要求:短期 sessionStorage + 定期刷新 Token

簡要說明:Token 是什么?

Token(令牌) 是一個用于身份驗證授權的字符串憑證,類似現(xiàn)實生活中的“門禁卡”或“鑰匙”。

核心特點

令牌形式:通常是 JWT(JSON Web Token)格式的字符串

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiIxMjM0NSIsImlhdCI6MTYxNjIzOTAyMn0.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

無狀態(tài):服務器不需要存儲 session,自身包含用戶信息

自包含:Token 本身包含了用戶身份信息和過期時間

Token 的工作流程(以登錄為例)

用戶登錄 → 服務器驗證 → 生成Token → 返回給客戶端
    ↓
客戶端存儲Token → 后續(xù)請求攜帶Token → 服務器驗證Token → 返回數(shù)據(jù)

Token 的結構(JWT 為例)

一個典型的 Token 包含三部分:

頭部.載荷.簽名

示例解析:

// 1. 頭部(Header)- 說明令牌類型和算法
{
  "alg": "HS256",  // 簽名算法
  "typ": "JWT"     // 令牌類型
}
// 2. 載荷(Payload)- 包含實際數(shù)據(jù)(用戶信息等)
{
  "userId": "12345",
  "username": "張三",
  "exp": 1640995200  // 過期時間戳
}
// 3. 簽名(Signature)- 用于驗證令牌真?zhèn)?
HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)

為什么使用 Token?

優(yōu)點:

  • 無狀態(tài):服務器不需要維護 session 存儲
  • 跨域友好:適合前后端分離和 API 調(diào)用
  • 移動端兼容:適合 App、小程序等
  • 可擴展性:容易實現(xiàn)分布式系統(tǒng)

缺點:

  • Token 泄露風險:一旦被盜用,攻擊者可以冒充用戶
  • 無法立即失效:需要額外的黑名單機制
  • 存儲安全問題:需要安全的存儲方式(localStorage 有 XSS 風險)

Token vs Cookie

特性TokenCookie
存儲位置localStorage / 內(nèi)存瀏覽器自動管理
跨域請求手動添加到 Header自動攜帶
安全性易受 XSS 攻擊易受 CSRF 攻擊
移動端支持有限

實際應用示例

// 客戶端:存儲和發(fā)送 Token
localStorage.setItem('token', 'your-jwt-token')
// 發(fā)送請求時攜帶 Token
fetch('/api/user', {
  headers: {
    'Authorization': `Bearer ${localStorage.getItem('token')}`
  }
})
// 服務器端:驗證 Token
app.get('/api/protected', (req, res) => {
  const token = req.headers.authorization?.split(' ')[1]
  if (!token) return res.status(401).send('無權限')
  // 驗證 Token 是否有效
  const decoded = jwt.verify(token, 'secret-key')
  // 如果有效,處理請求...
})

設置axios的通用頭

App.vue

<template>
  <div class="container">
    <Loader v-if="isLoading" text="正在加載??" background="rgba(0,0,0,0.8)"></Loader>
    <global-header :user="currentUser"></global-header>
    <router-view></router-view>
    <footer class="text-center py-4 text-secondary bg-light mt-6">
      <small>
        ......
      </small>
    </footer>
  </div>
</template>
<script lang="ts" setup>
import 'bootstrap/dist/css/bootstrap.min.css'
import GlobalHeader from './components/GlobalHeader.vue'
import { computed, onMounted } from 'vue'
import { useStore } from 'vuex'
import Loader from './components/Loader.vue'
import axios from 'axios'
const store = useStore()
const currentUser = computed(() => {
  return store.state.user
})
const isLoading = computed(() => {
  return store.state.loading
})
//獲取store中的token
const token = computed(() => {
  return store.state.token
})
onMounted(() => {
  //持久化登錄狀態(tài)
  //判斷用戶是否登錄
  if (!currentUser.value.isLogin && token.value) {
    //如果沒登錄,但是有token
    //設置axios的通用頭
    axios.defaults.headers.common['Authorization'] = `Bearer ${token.value}`
    //獲取用戶信息
    store.dispatch('fetchCurrentUser')
  }
})
</script>

一句話總結:Token 是一種數(shù)字鑰匙,客戶端持有它來證明自己的身份,服務器通過驗證這把鑰匙的真?zhèn)蝸頉Q定是否提供服務。

到此這篇關于Vue3 登錄狀態(tài)持久化方案詳解(Token 是什么)的文章就介紹到這了,更多相關Vue登錄狀態(tài)持久化內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • vue-cli axios請求方式及跨域處理問題

    vue-cli axios請求方式及跨域處理問題

    這篇文章主要介紹了vue-cli axios請求方式及跨域處理問題,文中還給大家提到了vue中axios解決跨域問題和攔截器使用,非常不錯,具有參考借鑒價值,需要的朋友參考下吧
    2018-03-03
  • Vue項目部署樣式全失效故障排查與修復指南

    Vue項目部署樣式全失效故障排查與修復指南

    Vue 項目打包后部署到新服務器,頁面出現(xiàn)白版或布局完全錯亂,但在本地和舊服務器上均顯示正常,本文檔用于指導前后端人員快速定位并解決此類資源加載成功但樣式失效的問題,需要的朋友可以參考下
    2026-05-05
  • vue3 emit is not a function問題及解決

    vue3 emit is not a function問題及解決

    這篇文章主要介紹了vue3 emit is not a function問題及解決方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-09-09
  • ElementUI日期選擇器時間選擇范圍限制的實現(xiàn)

    ElementUI日期選擇器時間選擇范圍限制的實現(xiàn)

    在日常開發(fā)中,我們會遇到一些情況,限制日期的范圍的選擇,本文就詳細的介紹了ElementUI日期選擇器時間選擇范圍限制的實現(xiàn),文中通過示例代碼介紹的非常詳細,感興趣的可以了解一下
    2022-04-04
  • vue數(shù)據(jù)響應式原理知識點總結

    vue數(shù)據(jù)響應式原理知識點總結

    在本篇文章里小編給各位整理的是一篇關于vue數(shù)據(jù)響應式原理知識點總結,有興趣的朋友們可以跟著學習下。
    2020-02-02
  • 詳談vue中router-link和傳統(tǒng)a鏈接的區(qū)別

    詳談vue中router-link和傳統(tǒng)a鏈接的區(qū)別

    這篇文章主要介紹了詳談vue中router-link和傳統(tǒng)a鏈接的區(qū)別,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-07-07
  • 解決antd的Form組件setFieldsValue的警告問題

    解決antd的Form組件setFieldsValue的警告問題

    這篇文章主要介紹了解決antd的Form組件setFieldsValue的警告問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-10-10
  • vue3中關于路由hash與History的設置

    vue3中關于路由hash與History的設置

    這篇文章主要介紹了vue3中關于路由hash與History的設置方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-08-08
  • vue2.0中vue-cli實現(xiàn)全選、單選計算總價格的實例代碼

    vue2.0中vue-cli實現(xiàn)全選、單選計算總價格的實例代碼

    本篇文章主要介紹了vue2.0中vue-cli實現(xiàn)全選、單選計算總價格的實例代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-07-07
  • Vue實現(xiàn)全選多個選擇框

    Vue實現(xiàn)全選多個選擇框

    使用v-model綁定布爾變量實現(xiàn)全選功能:定義數(shù)組存儲狀態(tài),使用v-for循環(huán)渲染選擇框,綁定狀態(tài);添加全選復選框,綁定布爾變量;使用watch監(jiān)聽全選復選框狀態(tài)變化,更新數(shù)組中每一項的狀態(tài)
    2025-01-01

最新評論

喜德县| 株洲市| 青岛市| 榆中县| 阳山县| 双峰县| 福安市| 驻马店市| 井陉县| 荃湾区| 沙田区| 五华县| 钟山县| 郎溪县| 车致| 当雄县| 广昌县| 海南省| 高尔夫| 什邡市| 武强县| 溆浦县| 共和县| 昆山市| 宁明县| 综艺| 临沂市| 渭南市| 右玉县| 崇仁县| 随州市| 永登县| 涿鹿县| 涟水县| 石城县| 临夏县| 南安市| 芜湖县| 招远市| 陇南市| 健康|