Home

blackshh

纸上得来终觉浅,绝知此事要躬行。

Blog About Email Github

laravel+vue跳转拦截器

这两天写项目的时候遇到的一个问题:基于laravel和vue实现的后台系统,实现跳转拦截,在前端页面跳转的时候判断用户是否已经登录,若没有就跳到登录界面。
总的来说,我有已下两种解决思路:

1. 在laravel中使用中间件,然后在渲染界面的时候使用中间件。

在laravel中的 /app/Http/Middleware/下定义了一个CheckLogin.php中间件,内容如下

namespace App\Http\Middleware;

use Closure;
use Illuminate\Support\Facades\Auth;

class CheckLogin
{
    /**
     * Handle an incoming request.
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        if(empty(Auth::id()))
            return  redirect('/');
        else    
            return $next($request);
    }
}

然后在Kernel.php中注册一下

    protected $routeMiddleware = [
        'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
            ...
        'checkLogin' => \App\Http\Middleware\CheckLogin::class,
    ];

然后再在 vue中的main.js中添加拦截器:

window.axios.interceptors.response.use(
    response => {
        return response;
    },
    error => {
        //请求错误时做些事
        if (error.response) {
            switch (error.response.status) {
                case 403:
                    location.href='/login';  
                    break;
                case 200:
                    window.location.href = "/";
                    break;
            }
        }
        return Promise.reject(error.response.data);

    });

2. 使用vue路由的requireAuth关键字,判断该路由的访问是否需要登录。

首先在定义路由的时候就需要多添加一个自定义字段requireAuth,用于判断该路由的访问是否需要登录。如果用户已经登录,则顺利进入路由, 否则就进入登录页面。在路由管理页面添加meta字段

import Vue from 'vue'
import Router from 'vue-router'

Vue.use(Router)
const routes = [
    {
        path: '/',
        name: "欢迎",
        meta: {
            requireAuth: true,  // 添加该字段,表示进入这个路由是需要登录的
        },
        component: resolve => require(["../components/Hello.vue"], resolve)
    },
    {
        path: '/login',
        name: "登录",
        component: resolve => require(["../view/login/login.vue"], resolve)
    }
]

定义完路由后,我们主要是利用vue-router提供的钩子函数beforeEach()对路由进行判断。

router.beforeEach((to, from, next) => {
  //NProgress.start();
  if (to.path == '/login') {
    sessionStorage.removeItem('user');
  }
  let user = JSON.parse(sessionStorage.getItem('user'));
  // 判断该路由是否需要登录权限,如果登录过会获取到user的信息。
  if (!user && to.path != '/login') {
    next({ path: '/login' })
  } else {
    next()
  }
})

每个钩子方法接收三个参数:

  • to: Route: 即将要进入的目标 路由对象
  • from: Route: 当前导航正要离开的路由
  • next: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。
  • next(): 进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是 confirmed (确认的)。
  • next(false): 中断当前的导航。如果浏览器的 URL 改变了(可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到 from 路由对应的地址。
  • next(‘/’) 或者 next({ path: ‘/’ }): 跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航。

确保要调用 next 方法,否则钩子就不会被 resolved。

其中,sessionStorage.getItem(‘user’) 获取用户信息,判断是否登录。我们需要在用户登录的时候记录下登录状态,就可以通过vue-router来阻止页面跳转了。

总结
这两种方法都可以实现跳转拦截,各自的优缺点的使用中间件可能会更安全,但使用中间件阻止跳转的的话,登录界面就不能引用中间件,所以需要把登录界面从vue后台中独立出来。使用vue-router阻止的话,别人可能会通过阻止js来绕过(我没试过,不确定),但是会更少的请求后台,项目目录也会更清晰。只能说各有各的特点。


blackshh

2017-08-28

Blog About Email Github