axios+vue登陸攔截。

路由攔截

第一步:路由攔截
首先在定義路由的時候就須要多添加一個自定義字段requireAuth,用於判斷該路由的訪問時候須要登陸。若是用戶已經登陸,則順利進入路由,不然就進入登陸頁面。前端

const routers=[
    {
        path:'/',
        name:'/',
        component:Index
    },
    {
        path:'/index',
        name:'index',
        meta:{
            requireAuth:true,//添加該字段,表示進入這個路由是須要登陸的。
        },
        component:index
    },
    {
        path:'/login',
        name:'login',
        component:Login
    },
]
//定義完路由後,咱們主要是利用vue-router提供的鉤子函數beforeEach()對路由進行判斷。
router.beforeEach((to,from,next)=>{
    if(to.meta.requireAuth){//判斷該路由是否須要登陸權限。
        if(store.state.token){//經過vuex state獲取當前的token是否存在。
            next();
        }else{
            next({
                path:'/login',
                query:{redirect:to.fullPath}//將跳轉的路由path做爲參數,登錄成功後跳轉到該路由
            })
        }
    }else{
        next();
    }
})

每一個鉤子方法接收三個參數:
*to:Route:即將要進入的目標路由對象。
*from:Route:當前導航正要離開的路由。
*next:Function:必定要調用該方法來resolve這個鉤子。執行效果依賴next方法的調用參數。
*next();進行管道中的下一個鉤子。若是所有鉤子執行完了,則導航的狀態就是confirmed。
*next(false):中斷當前的導航。若是瀏覽器的URL改變了,那麼》URL地址會重置到from路由對應的地址。(多是用戶手動或者瀏覽器後退按鈕)
*next('/')或則next({path:'/'}):跳轉到一個不一樣的地址。當前的導航被中斷,而後進行一個新的導航。
確保要調用next方法,不然鉤子就不會被resolved。vue

其中,to.meta中是咱們自定義的數據,其中就包括咱們剛剛定義的requireAuth字段。經過這個字段來判斷該路由是否須要登陸權限。須要的話,同時當前應用不存在token,則跳轉到登陸頁面,進行登陸。登錄成功後跳轉到目標路由。
登陸攔截到這裏就結束了碼?並無。這種方式只是簡單的前端路由控制,並不能真正的阻止用戶訪問須要登錄權限的路由。還有一種狀況是:當前token失效了,可是token依然保存在本地。這時候你去訪問須要登錄權限的路由時,實際上應該讓用戶從新登陸。
這時候就須要結合http攔截器+後端接口返回的http狀態碼來判斷。

第二步:
要想統一處理http請求和響應,就得用axios的攔截器。經過配置http response inteceptor,當後端接口返回401,讓用戶從新登陸。ios

//http request攔截器。
axios.interceptors.request.use(
    config=>{
        if(store.state.token){
            config.headers.Authorization = `token${store.state.token}`;
        }
        return config;
    },
    err=>{
        return Promise.reject(err);
    }
);
//http response攔截器
axios.interceptors.response.use(
    response=>{
        return response;
    }
    error=>{
        if(error.response){
            switch(error.response.status){
                case 401:
                    //返回401清楚token信息並跳轉到登錄頁面
                    store.commit(types.LOGOUT);
                    router.replace({
                        path:'/login',
                        query:{redirect:router.currentRoute.fullPath}
                    })
            }
        }
        return Promise.reject(err.response.data)//返回接口返回的錯誤信息。
    }
)

補充一個最全的axios的配置增長了get和post的方法封裝,由於post方法傳參老是須要qs來序列化請求參數。vue-router

//請求攔截、相應攔截、錯誤統一處理。
import axios from 'axios';
import QS from 'qs';
import store from '../store/index';
//環境的切換
if(process.env.NODE_ENV == 'development'){
    axios.defaults.baseUrl = '/api';
}else if(process.env.NODE_ENV == 'debug'){
    axios.de
    faluts.baseURL = '';
}else if(process.env.NODE_ENV == 'production'){
    axios.defaults.baseURL= 'http://api.123dailu.com/';
}
//請求超時時間
axios.defaults.timeout = 10000;
//post請求頭
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8';
//請求攔截器
axios.interceptors.request.use(
    config=>{
        //每次發送請求以前判斷是否存在token,若是存在,則統一在http請求的header都加上token,不用每次請求都手動添加了。
        //即便本地存在token,也有可能token是過時的,因此在響應攔截器中要對返回狀態進行判斷。
        const token = store.state.toekn;
        token && (config.headers.Authorization = toekn);
        return config;
    },
    err =>{
        return Promise.error(err);
    }
)
//響應攔截器
axios.inteceptors.response.use(
    respones=>{
        if(response.status == 200){
            return Promise.resolve(response);
        }else{
            return Promise.reject(response);
        }
    },
    //服務器狀態碼不是200的狀況
    error=>{
        if(error.response.status){
            switch(error.response.status){
                //401:未登陸
                //未登陸則跳轉登陸頁面,並攜帶當前頁面的路徑。
                //在登陸成功後返回當前頁面,這一步須要在登陸頁操做。
                case 401:
                    router.replace({
                        path:'/login',
                        query:{redirect:router.currentRoute.fullPath}
                    });
                    break;
                //登陸過時對用戶進行提示。
                //清除本地token和清空vuex中的token對象。
                //跳轉登陸頁面。
                case 403:
                    Toast({
                        message:'登陸過時,請從新登陸',
                        duration:1000,
                        forbidClick:true
                    });
                    //清除token
                    localStorage.removeItem('token');
                    store.commit('loginSuccess',null);
                    //跳轉登錄頁面,並將要瀏覽的頁面fullPath傳過去,登陸成功後跳轉須要訪問的頁面。
                    setTimeout(() => {                        
                        router.replace({                            
                            path: '/login',                            
                            query: { 
                                redirect: router.currentRoute.fullPath 
                            }                        
                        });                    
                    }, 1000);
                    break;
            }
            return Promise.reject(error.response);   
        }
    }
)
/** 
 * get方法,對應get請求 
 * @param {String} url [請求的url地址] 
 * @param {Object} params [請求時攜帶的參數] 
 */
export const get =(url, ...params)=>{    
    return new Promise((resolve, reject) =>{        
        axios.get(url, {            
            params: params        
        })        
        .then(res => {            
            resolve(res.data);        
        })        
        .catch(err => {            
            reject(err.data)        
        })    
    });
}
/** 
 * post方法,對應post請求 
 * @param {String} url [請求的url地址] 
 * @param {Object} params [請求時攜帶的參數] 
 */
export const post = (url,... params) =>{    
    return new Promise((resolve, reject) => {         
        axios.post(url, QS.stringify(...params))        
        .then(res => {            
            resolve(res.data);        
        })        
        .catch(err => {            
            reject(err.data)        
        })    
    });
}

使用vue-cookies+axios實現登陸攔截

1.安裝vue-cookiesvuex

npm install vue-cookies --save;

2.在登陸接口中設定cookiesnpm

this.$http.post(global.domin+'/login/check',{
    uesrname:this.ruleForm.username,
    password:this.ruleForm.password
}).then(function(response){
    var dataObj = respones.data;
    if(dataObj.code==200){
        that.token = dataObj.data.token;
        that.$cookies.set('token',that.token,'45d');//第三個參數是過時時間。
    }
}).catch(function(error){
    console.log(error);
})

3.在main.js中設置攔截器。axios

//攔截器 每一個接口加token
axios.interceptors.request.use(function(config){
    if(VueCookies.get('token')){
        config.headers.Authorization = String(VueCookies.get('token'))
        //具體是什麼樣的頭,和後端匹配。
    };
    return config;
},function(error){
    return Promise.reject(error);
});
//沒有就從新登陸
axios.interceptors.response.use(function(response){
    // console.log(response)
    // if(response.data.code == 401) {
    //     router.replace({
    //         name: 'login'
    //     });
    // }
    return response;
},function(error){
    if(error.response.status==401){
        router.replace({
            name:'login'
        })
    }
    return Promise.reject(error)//用上面的成功的仍是下面報錯的根據需求。
})
相關文章
相關標籤/搜索