VueJs结合Vuex与localStorage登录成功后后续请求返回401错误
问题核心原因
出现该问题的本质是token更新后,请求模块没有实时获取到最新的token值,初始化时读取的是页面首次加载的旧token(空值),刷新浏览器后才会重新读取最新存储的token,所以才会出现刷新后请求正常的现象。
具体解决方案
- 第一步:补全Vuex mutation的持久化逻辑
你当前的token mutation只更新了内存中的state值,虽然你登录时手动存了localStorage,但统一在mutation中处理可以避免逻辑遗漏,修改后的代码如下:
import { createStore } from 'vuex'; const store = createStore({ strict: false, state: { token: localStorage.getItem('token'), isLoggedIn: !!localStorage.getItem('token') }, getters: {}, mutations: { setToken(state,payload) { state.token = payload // 同步更新localStorage,保证持久化存储和state值一致 localStorage.setItem('token', payload) state.isLoggedIn = !!payload localStorage.setItem('isLoggedIn', state.isLoggedIn) } }, actions: {} }); export default store
登录时只需执行commit('setToken', 接口返回的token)即可,不需要单独写localStorage存储逻辑。
- 第二步:修正axios拦截器的取值逻辑
绝大多数人踩的坑是:在拦截器外一次性读取token,导致后续token更新后拦截器拿到的还是旧值。必须保证每次发起请求前都读取最新的token,正确的拦截器写法如下:
import axios from 'axios' const request = axios.create({ baseURL: '你的接口基础地址', timeout: 10000 }) // 请求拦截器:每次请求前都会执行 request.interceptors.request.use( config => { // 每次都从localStorage取最新的token,不要把这行代码写在拦截器外面 const token = localStorage.getItem('token') if (token) { // 注意Bearer和token之间必须有一个空格,格式错误也会导致401 config.headers.Authorization = `Bearer ${token}` } return config }, error => { return Promise.reject(error) } ) export default request
后续所有接口请求都统一使用这个封装好的axios实例,不要直接用原生axios发请求。
- 第三步:验证排查
如果修改后还是401,按以下顺序排查:
- 登录后打开浏览器调试工具Application面板,查看localStorage的token值是否和接口返回的一致
- 打开Network面板,查看发起的请求的Request Headers中是否携带了Authorization字段,值的格式是否为
Bearer 你的token字符串,没有拼写错误、多余符号 - 确认后端鉴权逻辑是否要求其他额外头字段,比如
Content-Type等,缺失也可能触发401
内容的提问来源于stack exchange,提问作者Maarten Van Hoecke
相关产品推荐
相关产品推荐

