Vuejs Laravel Passport-如果访问令牌过期怎么办?

时间:2019-05-31 06:15:26

标签: laravel vue.js token vuex laravel-passport

我正在使用带有Laravel API的Vuejs SPA作为后端。我成功获取了个人访问令牌,并将其存储在localStorage和Vuex状态中,如下所示。

token: localStorage.getItem('token') || '',
expiresAt: localStorage.getItem('expiresAt') || '',

每次向laravel API发送axios请求时,我都会使用访问令牌。一切正常。但是,最初将令牌设置为1年到期,所以当我开发令牌时,我并不关心令牌是否过期,而今天突然间,我想到了如果令牌过期会发生什么。因此,我在laravel AuthServiceProvier.php中将令牌过期设置为10秒。

Passport::personalAccessTokensExpireIn(Carbon::now()->addSecond(10));

,然后我登录,10秒钟后,由于令牌已过期并出现401未经授权的错误,每个请求都停止工作。

在这种情况下,如何知道令牌是否已过期?如果用户使用网站时令牌已过期,我想将用户重定向到登录页面。

3 个答案:

答案 0 :(得分:0)

这就是我的工作。如果响应代码为4xx或5xx,则Axios将引发错误,然后添加一个if来检查响应状态是否为401,然后重定向到登录页面。

export default {
    methods: {
        loadData () {
            axios
                .request({
                    method: 'get',
                    url: 'https://mysite/api/route',
                })
                .then(response => {
                    // assign response.data to a variable
                })
                .catch(error => {
                    if (error.response.status === 401) {
                        this.$router.replace({name: 'login'})
                    }
                })
        }
    }
}

但是,如果您这样做,则必须将捕获的内容复制粘贴到程序内部的所有axios调用上。 我这样做的方法是将上面的代码放入javascript文件api.js,将类导入main.js,然后将其分配给Vue.prototype。$ api

import api from './api'
Object.defineProperty(Vue.prototype, '$api', { value: api })

所以在我的组件中,我只是这样称呼axios。

this.$api.GET(url, params)
    .then(response => {
        // do something
    })

该错误是在api.js上处理的。 这是我完整的api.js

import Vue from 'vue'
import axios from 'axios'
import router from '@/router'

let config = {
  baseURL : process.env.VUE_APP_BASE_API,
  timeout : 30000,
  headers : {
    Accept         : 'application/json',
    'Content-Type' : 'application/json',
  },
}

const GET = (url, params) => REQUEST({ method: 'get', url, params })
const POST = (url, data) => REQUEST({ method: 'post', url, data })
const PUT = (url, data) => REQUEST({ method: 'put', url, data })
const PATCH = (url, data) => REQUEST({ method: 'patch', url, data })
const DELETE = url => REQUEST({ method: 'delete', url })

const REQUEST = conf => {
  conf = { ...conf, ...config }
  conf = setAccessTokenHeader(conf)

  return new Promise((resolve, reject) => {
    axios
      .request(conf)
      .then(response => {
        resolve(response.data)
      })
      .catch(error => {
        outputError(error)
        reject(error)
      })
  })
}

function setAccessTokenHeader (config) {
  const access_token = Vue.cookie.get('access_token')
  if (access_token) {
    config.headers.Authorization = 'Bearer ' + access_token
  }

  return config
}

/* https://github.com/axios/axios#handling-errors */
function outputError (error) {
  if (error.response) {
    /**
     * The request was made and the server responded with a
     * status code that falls out of the range of 2xx
     */
    if (error.response.status === 401) {
      router.replace({ name: 'login' })
      return
    }
    else {
      /* other response status such as 403, 404, 422, etc */
    }
  }
  else if (error.request) {
    /**
     * The request was made but no response was received
     * `error.request` is an instance of XMLHttpRequest in the browser
     * and an instance of http.ClientRequest in node.js
     */
  }
  else {
    /* Something happened in setting up the request that triggered an Error */
  }
}

export default {
  GET,
  POST,
  DELETE,
  PUT,
  PATCH,
  REQUEST,
}

答案 1 :(得分:0)

尽可能地方便用户使用。与其等到令牌到期后才收到401错误响应,然后再重定向,不如在主SPA实例的已挂接钩子上设置令牌验证检查,并使其对例如/validatePersonalToken在服务器上,然后在路由或控制器中执行类似的操作。

Route::get('/validatePersonalToken', function () {
      return ['message' => 'is valid'];
})->middleware('auth:api');

如果令牌无效,它将返回"error": "Unauthenticated"。这样一来,用户将被指示在继续操作之前进行身份验证,以使用该应用程序并提交数据,然后可能丢失工作(例如提交表单),而这不是非常用户友好的。

您可以通过使用Vue Mixin在逐个组件的基础上而不是在主实例上执行此操作。对于寿命很短的令牌(使用该应用程序时可能会过期),这会更好。将检查放入mixin的mounted()挂钩中,然后在任何进行api调用的组件中使用该mixin,以便在安装该组件时运行检查。 https://vuejs.org/v2/guide/mixins.html

答案 2 :(得分:0)

你可以使用带有 axios 的拦截器。捕获 401 并清除本地存储,然后将用户重定向到适当的页面。