Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/vue.js/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Vue.js 在路由进入Vue路由器之前检查验证令牌是否有效_Vue.js_Vuejs2_Vue Component_Vue Router_Vuex - Fatal编程技术网

Vue.js 在路由进入Vue路由器之前检查验证令牌是否有效

Vue.js 在路由进入Vue路由器之前检查验证令牌是否有效,vue.js,vuejs2,vue-component,vue-router,vuex,Vue.js,Vuejs2,Vue Component,Vue Router,Vuex,我有一个简单的用例,我的应用程序使用vue路由器和vuex。然后,store包含一个user对象,该对象开头为null。从服务器验证用户后,它会发回一个user对象,该对象包含一个JWTauth令牌,该令牌分配给存储中的user对象。现在,假设用户在3小时后返回并尝试访问某个路由或执行任何其他操作,考虑到auth令牌已过期,那么最好的方法是什么(需要调用axios post进行检查)并将用户重定向到登录页面。我的应用程序将有大量组件,因此我知道我可以编写逻辑来检查每个组件的挂载的钩子中的令牌是否

我有一个简单的用例,我的应用程序使用
vue路由器
vuex
。然后,
store
包含一个
user
对象,该对象开头为
null
。从服务器验证用户后,它会发回一个
user
对象,该对象包含一个
JWT
auth令牌,该令牌分配给存储中的
user
对象。现在,假设用户在3小时后返回并尝试访问某个路由或执行任何其他操作,考虑到auth令牌已过期,那么最好的方法是什么(需要调用
axios post
进行检查)并将用户重定向到
登录
页面。我的应用程序将有大量组件,因此我知道我可以编写逻辑来检查每个组件的
挂载的
钩子中的令牌是否有效,但这意味着重复所有组件。另外,我不想在每次
导航前使用
,因为我无法向用户显示任何视觉反馈,比如检查…
或加载…

我在我的一个项目中做了类似的事情,实际上很难处理这些类型的情况,但是,您可以在进入受保护路由之前添加一个
保护,然后在身份验证失败时重定向

const guard = function(to, from, next) {
  // check for valid auth token
  axios.get('/api/checkAuthToken').then(response => {
      // Token is valid, so continue
      next();
  }).catch(error => {
      // There was an error so redirect
      window.location.href = "/login";
  })
};
然后在您的路线上,您可以执行以下操作:

{
  path: '/dashboard',
  component: Dashboard,
  beforeEnter: (to, from, next) => {
    guard(to, from, next);
  }
},
您可能注意到我使用的是
location.href
而不是
router.push
。我这样做是因为我的登录表单受csrf保护,所以我需要一个新的csrf_令牌

你的另一个问题是,如果用户试图在不改变路线的情况下与你的页面交互(即,他们单击按钮并得到401响应)。为此,我发现最容易检查每个
axios
请求的身份验证,并在收到401响应时重定向到
login


就在保护检查期间添加加载微调器而言,您只需向vuex存储添加加载标志,然后将存储导入路由器。老实说,虽然我不想麻烦,但在一台像样的生产服务器上,检查会很快完成,用户不太可能看到它。

您可以使用
拦截器
在某些请求发生时以静默方式获取身份验证令牌

    axios.interceptors.response.use(function (response) {
         return response;
       }, function (error) {

              const originalRequest = error.config;

             if (error.response.status === 401 && !originalRequest._retry) {

              originalRequest._retry = true;

              const rToken = window.localStorage.getItem('rToken');
              return axios.post('url/to/get/refresh/token', { rToken })
                     .then(({data}) => {
                     window.localStorage.setItem('token', data.token);
                     window.localStorage.setItem('rToken', data.refreshToken);
                     axios.defaults.headers.common['Authorization'] = 'Bearer ' + data.token;
                    originalRequest.headers['Authorization'] = 'Bearer ' + data.token;
                    return axios(originalRequest);
           });
      }

      return Promise.reject(error);
   });
试试Vue.JS 您可以定义全局Mixin并通过Vue使用它。使用(myMixin)
-然后所有组件都将继承此Mixin。如果您在mixin上定义了一个
挂载的
或可能更好的
激活的
钩子,它将在每个组件上被调用

在那里,您可以使用组件所能做的一切-
将指向您的组件。如果组件本身也定义了一个钩子,那么相同类型的mixin钩子将在组件拥有钩子之前运行

或者尝试一个顶级登录组件 我们使用了一个稍有不同的解决方案-我们有一个单独的组件来处理所有与登录相关的内容,它存在于父index.html中路由器视图之外。此组件始终处于活动状态,可以隐藏div路由器视图并覆盖加载消息或登录屏幕。对于intranet应用程序,只要浏览器保持打开状态,该组件还将使用轮询保持会话活动


您可以将路由器导航加载到此组件。-因此,要触发路由器导航的子组件只需将一个全局反应属性
navigateTo
设置为顶级身份验证组件监视的状态。这将触发身份验证检查,可能是登录工作流,然后顶级组件将调用
$router.push()
,使用这种方法,您可以完全控制任何导航。

因为您使用
vuex
,所以可以添加一些状态,如
isLoading
isChecking

在您的
路由器中。在每次
之前,您可以检查并设置
正在加载
正在检查
,以遵循您当前的检查状态。然后,您可以按照此状态显示加载消息

在route.js中,我们在用户拥有令牌或 不是

route.js

{
   path: '/dashboard',
   name: dashboard,
   meta: {
     layout: 'home-layout'
   },
   components: {
     default: Dashboard,
     header: UserHeader
   },
   beforeEnter: ifAuthenticated,
 }
const ifAuthenticated = (to, from, next) => {
 if (localStorage.getItem(token)) {
   next();
   return;
 }
 router.push({ 
   name: 'login',
   params: {
     returnTo: to.path,
     query: to.query,
   },
 });
};
route.js

{
   path: '/dashboard',
   name: dashboard,
   meta: {
     layout: 'home-layout'
   },
   components: {
     default: Dashboard,
     header: UserHeader
   },
   beforeEnter: ifAuthenticated,
 }
const ifAuthenticated = (to, from, next) => {
 if (localStorage.getItem(token)) {
   next();
   return;
 }
 router.push({ 
   name: 'login',
   params: {
     returnTo: to.path,
     query: to.query,
   },
 });
};

假设我在mixin中安装了一个
挂载的
钩子,那么如何确保在某些操作完成之前不调用组件级别的
挂载的
?我认为没有一种干净的方法可以做到这一点。更好的方法是为此操作定义一个新的自定义选项名称。例如,
ready
——并定义Mixin方法,以便在操作完成后调用组件的
ready
方法(如果组件有)。一个mixin注册自定义“ready”函数的示例,在一些ajax调用或类似操作完成后调用该函数……我不会将`window.location.href`与一起使用vuerouter@deathangel908这是为了刷新一个Laravel CSRF令牌,该令牌将在一段时间不活动后过期,因此,在这一点上,路由器推送意味着用户需要手动刷新该页面才能登录,我发现更容易强制会话刷新登录页面。这只是Laravel的一个怪癖,必须加以解决,否则我不会这么做。
guard
函数使页面永远重定向到自身。您是否将其视为路由器内的异步中间件?如果组件中没有请求,该怎么办?尽管您的令牌已过期,您仍将被允许导航如果令牌在服务器端强制过期,您将被允许导航,因为您的本地存储仍然包含令牌密钥