在前端开发中,统一处理用户认证(如Token)是提升代码复用性和安全性的重要手段。Vue作为流行的前端框架,结合拦截器(Interceptor)机制可以高效实现这一目标。然而,IE9等旧浏览器的兼容性问题常成为技术落地的障碍。本文将详细阐述如何基于Vue生态构建统一的Token拦截器,并解决IE9环境下的兼容性挑战,涵盖从基础原理到完整实现的完整流程。
一、Token认证与拦截器基础
Token认证是现代Web应用中常见的身份验证方式,客户端在登录后获取服务器颁发的Token,后续请求通过携带Token证明身份。传统实现方式中,开发者需在每个API调用前手动添加Token,导致代码冗余且难以维护。拦截器通过封装请求/响应的公共逻辑,可实现Token的自动注入和错误统一处理。
1.1 拦截器工作原理
拦截器本质上是请求/响应管道中的中间件,可在数据发送前(请求拦截)或接收后(响应拦截)修改或中断流程。以axios为例,其提供的`interceptors.request`和`interceptors.response`方法允许开发者注册全局处理函数。
1.2 Token存储方案
Token通常存储在以下位置:
- localStorage:持久化存储,但IE9以下版本兼容性差
- sessionStorage:会话级存储,同样存在IE兼容问题
- cookie:自动随请求发送,但需处理CSRF且容量有限
- 内存变量:临时存储,页面刷新后丢失
针对IE9,需优先选择cookie或降级存储方案。
二、Vue项目中的Token拦截器实现
以下以Vue CLI创建的项目为例,结合axios实现统一Token管理。
2.1 创建axios实例
// src/utils/request.js
import axios from 'axios'
const service = axios.create({
baseURL: process.env.VUE_APP_BASE_API,
timeout: 5000
})
2.2 请求拦截器实现
在发送请求前自动从存储中读取Token并添加到Header:
// 存储Token的函数(兼容IE9)
function getToken() {
// 优先使用localStorage,降级到cookie
if (window.localStorage) {
return localStorage.getItem('token')
} else {
// IE9及以下版本从cookie读取
const cookies = document.cookie.split(';')
for (let i = 0; i {
const token = getToken()
if (token) {
config.headers['Authorization'] = `Bearer ${token}`
}
return config
},
error => {
return Promise.reject(error)
}
)
2.3 响应拦截器实现
统一处理Token过期或无效的情况:
service.interceptors.response.use(
response => {
const res = response.data
if (res.code !== 200) {
// 示例:401未授权处理
if (res.code === 401) {
// 跳转登录页逻辑
window.location.href = '/login'
return Promise.reject('未授权')
}
return Promise.reject(res.message || 'Error')
} else {
return res
}
},
error => {
return Promise.reject(error)
}
)
2.4 封装全局请求方法
在Vue原型上挂载请求方法,方便组件调用:
// src/main.js
import { service } from './utils/request'
Vue.prototype.$http = service
组件中使用示例:
this.$http.get('/api/user').then(res => {
console.log(res.data)
})
三、IE9兼容性解决方案
IE9对ES6特性、Promise、localStorage等支持有限,需通过polyfill和降级方案解决。
3.1 配置Babel转译
在babel.config.js中添加core-js@3的按需引入:
module.exports = {
presets: [
['@vue/cli-plugin-babel/preset', {
useBuiltIns: 'usage',
corejs: 3
}]
]
}
3.2 Promise兼容
引入es6-promise或core-js的Promise实现:
// src/main.js
import 'es6-promise/auto' // 或通过core-js引入
3.3 localStorage降级方案
封装统一的存储方法,自动选择可用存储:
// src/utils/storage.js
const Storage = {
set(key, value) {
if (window.localStorage) {
localStorage.setItem(key, value)
} else {
// IE9及以下使用document.cookie
const expires = new Date(Date.now() + 86400e3).toUTCString()
document.cookie = `${key}=${value}; expires=${expires}; path=/`
}
},
get(key) {
if (window.localStorage) {
return localStorage.getItem(key)
} else {
const cookies = document.cookie.split(';')
for (let i = 0; i
3.4 XMLHTTPRequest降级
极特殊情况下(如axios完全失效),可手动封装兼容请求:
function ieCompatibleRequest(url, method, data) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest()
xhr.open(method, url)
xhr.setRequestHeader('Content-Type', 'application/json')
// 从Storage获取Token
const token = Storage.get('token')
if (token) {
xhr.setRequestHeader('Authorization', `Bearer ${token}`)
}
xhr.onload = () => {
if (xhr.status >= 200 && xhr.status reject('Network Error')
xhr.send(JSON.stringify(data))
})
}
四、完整实现示例
综合上述方案,完整的Vue Token拦截器实现如下:
4.1 封装request工具类
// src/utils/request.js
import axios from 'axios'
import { Storage } from './storage'
import 'es6-promise/auto'
// 创建axios实例
const service = axios.create({
baseURL: process.env.VUE_APP_BASE_API,
timeout: 10000
})
// 请求拦截器
service.interceptors.request.use(
config => {
const token = Storage.get('token')
if (token) {
config.headers['Authorization'] = `Bearer ${token}`
}
return config
},
error => Promise.reject(error)
)
// 响应拦截器
service.interceptors.response.use(
response => {
const res = response.data
if (res.code !== 200) {
if (res.code === 401) {
// 处理Token过期
Storage.remove('token')
window.location.href = '/login'
return Promise.reject('登录已过期')
}
return Promise.reject(res.message || '请求错误')
}
return res
},
error => {
if (error.response) {
switch (error.response.status) {
case 401:
// 同上处理
break
default:
console.error('请求错误:', error.response.status)
}
}
return Promise.reject(error)
}
)
export default service
4.2 Vue组件中使用
// src/views/User.vue
export default {
methods: {
fetchUser() {
this.$http.get('/api/user').then(res => {
this.userInfo = res.data
}).catch(err => {
this.$message.error(err)
})
}
},
mounted() {
this.fetchUser()
}
}
五、测试与验证
为确保IE9兼容性,需进行以下测试:
- 使用IE9模拟器或虚拟机访问应用
- 验证登录后Token是否正确存储到cookie
- 检查后续请求是否自动携带Token
- 模拟Token过期场景,验证重定向逻辑
- 测试Promise异常处理是否生效
六、性能优化建议
- Token验证接口应尽量轻量,避免阻塞主流程
- 对频繁请求的接口可添加本地缓存
- 使用axios的CancelToken取消重复请求
- IE9环境下减少同步存储操作,使用防抖优化
七、常见问题解决方案
7.1 IE9中axios无法发送请求
原因:IE9不支持Promise或某些ES6语法。解决方案:
- 确保已引入es6-promise
- 检查babel配置是否包含@babel/polyfill
- 降级使用XMLHTTPRequest
7.2 Token未自动添加到请求头
排查步骤:
- 检查Storage.get('token')是否返回有效值
- 验证拦截器注册顺序是否正确
- 查看网络请求的Headers是否包含Authorization
7.3 跨域问题导致Token失效
解决方案:
- 配置服务器CORS头:`Access-Control-Allow-Headers: Authorization`
- 开发环境使用代理配置(vue.config.js)
- 生产环境确保域名一致或正确配置CORS
八、总结与扩展
通过拦截器实现统一Token管理可显著提升开发效率,而兼容IE9的关键在于:
- 提供可靠的存储降级方案
- 完善ES5/ES6特性兼容
- 详细的错误处理和日志记录
未来可扩展的方向包括:
- 添加请求重试机制
- 集成JWT解析库自动刷新Token
- 实现多环境Token管理
- 添加请求耗时统计和性能监控
关键词:Vue拦截器、Token认证、IE9兼容、axios、Promise降级、localStorage降级、Babel配置、XMLHTTPRequest
简介:本文详细介绍了在Vue项目中通过拦截器实现统一Token认证的完整方案,重点解决了IE9浏览器的兼容性问题。内容涵盖axios拦截器基础、Token存储与自动注入、Promise和localStorage的降级实现、Babel转译配置以及完整代码示例,适合需要支持旧浏览器的企业级前端项目参考。