vue3+axios实现登录拦截 配置axios封装

发布时间:2023-03-03 11:30

项目结构 

├── dist  // 打包构建后的文件夹
├── node_modules //该项目依赖的模块
├── public  //存放静态资源(不会变动)
├── src
│   ├── assets  //存放css、图片与js文件
│   │    ├── css
│   │    ├── img
│   │    └── js
│   ├── components  //存放可复用的小组件
│   ├── http        // 封装fetch、post请求及http 拦截器配置文件
│   │    ├── api.js
│   │    └── axios.js
│   ├── router      //路由配置文件
│   │    └── index.js
│   ├── store       //vuex
│   │    └── index.js
│   ├── views       //存放主要页面(不可复用的页面组件)
│   ├── App.vue
│   └── main.js
├── .gitignore
├── babel.config.js
├── package-lock.json
├── package.json
├── README.md
└── vue.config.js

登录拦截逻辑

一:路由拦截

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

// src/router/index.js
const routes = [
    {
        path: \'/home\',
        name: \'/home\',
        component: () => import(\'../views/home/home.vue\')
    },
    {
        path: \'/user\',
        name: \'user\',
        meta: {
            requireAuth: true,  // 添加该字段,表示进入这个路由是需要登录的
        },
        component: () => import(\'../views/user/user.vue\')
    },
    {
        path: \'/login\',
        name: \'login\',
        component: () => import(\'../views/login/login.vue\')
    }
];

vue-router提供的钩子函数beforeEach()对路由进行判断。

//src/router/index.js
//根据我们的项目需求
router.beforeEach((to,from,next)=>{
	if(to.meta.requireAuth){  // 判断该路由是否需要登录权限
        if(localStorage.getItem(\"access_token\")) {  // 从本地存储localStorage获取当前的token是否存在
            next()
        }else{
            next(\'/home\') //如果token不存在,就跳到首页
        }
	}else{
        if(localStorage.getItem(\"access_token\") && to.path == \'/login\') {  //token存在时候,进去登录页面就自动跳转到首页
            next(\'/home\')
        }else{
            next()
        }
    }
});

 完整的代码,如下:

import Vue from \'vue\'
import VueRouter from \'vue-router\'

Vue.use(VueRouter)

const routes = [
    {
        path: \'/home\',
        name: \'/home\',
        component: () => import(\'../views/home/home.vue\')
    },
    {
        path: \'/user\',
        name: \'user\',
        meta: {
            requireAuth: true,  // 添加该字段,表示进入这个路由是需要登录的
        },
        component: () => import(\'../views/user/user.vue\')
    },
    {
        path: \'/login\',
        name: \'login\',
        component: () => import(\'../views/login/login.vue\')
    }
];

const router = new VueRouter({
    // mode: \'history\',
    base: process.env.BASE_URL,
    routes
})

router.beforeEach((to,from,next)=>{
	if(to.meta.requireAuth){  // 判断该路由是否需要登录权限
        if(localStorage.getItem(\"access_token\")) {  // 从本地存储localStorage获取当前的token是否存在
            next()
        }else{
            next(\'/home\') //如果token不存在,就跳到首页
        }
	}else{
        if(localStorage.getItem(\"access_token\") && to.path == \'/login\') {  //token存在时候,进去登录页面就自动跳转到首页
            next(\'/home\')
        }else{
            next()
        }
    }
});

export default router

二:拦截器

使用axios的拦截器,统一处理所有http请求和响应。根据我们的项目需求,配合后台接口返回账号被迫下线或者返回401 Unauthorized(未授权),让用户重新登陆。

// src/http/axios.js
import axios from \'axios\'
import { Modal, message } from \'ant-design-vue\'
import router from \'@/router\'

axios.defaults.timeout = 10000 // 请求超时时间

const Service = axios.create({
    baseURL: \'/\',
})

// axios 请求拦截器
Service.interceptors.request.use(
    config=>{
        if(localStorage.getItem(\"access_token\")){
			config.headers.Authorization = \'Bearer\' + \'  \' + localStorage.getItem(\'access_token\');
        }
        return config
    },error=>{
        Modal.confirm({
            title: \'提示\',
            content: \'请求超时!\',
        });
        return Promise.reject(error)
    }
)

//有的一个页面请求几个接口,当token过期或者账号被迫下线,避免出现多个弹窗,自定义cont,判断cont==0时候弹窗一次,然后cont++
let cont = 0 
// axios respone拦截器
Service.interceptors.response.use(
    res=>{
        if(res.status == 200){
            if(res.data.message && res.data.message.type == \'logout\'){
                if(cont == 0){
                    Modal.info({
                        title: \'信息\',
                        content: \"你的账号在别处登陆,请注意!\",
                        onOk() {
                            cont = 0
                        }
                    })
                    localStorage.removeItem(\'access_token\');
                    localStorage.removeItem(\'expires_time\');
                    if(router.history.current.path != \'/home\'){
                        router.push(\'/home\');
                    }
                }
                cont ++;
            }

            return res;
        }else if (res.status == 401){
            router.push(\'/home\');
            return res;
        }else if (res.status == 201) {
            return res;
        }
        return res;
    },
    error=>{
        const responseCode = error.response.status;
        switch (responseCode) {
        case 400:
            message.error(\'请求错误(400)\')
            break
        case 401:
            if(cont == 0) {
                message.error(\'登录过期,请重新登录\')
            }
            cont++
            llocalStorage.removeItem(\'access_token\');
            localStorage.removeItem(\'expires_time\');
            if(router.history.current.path != \'/home\'){
                router.push(\'/home\');
            }
            break
        case 403:
            message.error(\'拒绝访问(403)\')
            break
        case 404:
            message.error(\'请求出错(404)\')
            break
        case 408:
            message.error(\'请求超时(408)\')
            break
        case 500:
            message.error(\'服务器错误(500)\')
            break
        case 501:
            message.error(\'服务未实现(501)\')
            break
        case 502:
            message.error(\'网络错误(502)\')
            break
        case 503:
            message.error(\'服务不可用(503)\')
            break
        case 504:
            message.error(\'网络超时(504)\')
            break
        case 505:
            message.error(\'HTTP版本不受支持(505)\')
            break
        default:
            Modal.confirm({
                title: \'提示\',
                content: `连接出错(${error.response.status})!`,
            });
        }
        return Promise.reject(error.response.data)
    }
)

export default Service;

调用接口

// src/http/api.js
import Service from \'./axios.js\'

// 登录
export const loginApi = data => {
    return Service({
        url: \'/api/authorizations\',
        method: \'post\',
        data
    })
};

// 用户信息
export const userApi = data => {
    return Service({
        url: \'/api/user\' + data,
        method: \'get\',
    })
}

登出

很简单,只需要从本地存储localStorage中当前token清除,再跳转到首页即可。

本文章根据我们的项目需求,作为个人思路笔记,仅供参考。

ItVuer - 免责声明 - 关于我们 - 联系我们

本网站信息来源于互联网,如有侵权请联系:561261067@qq.com

桂ICP备16001015号