成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

詳解基于vue,vue-router, vuex以及addRoutes進(jìn)行權(quán)限控制

eternalshallow / 1090人閱讀

摘要:基于的權(quán)限控制教程,完整代碼地址見接下來讓我們模擬一個(gè)普通用戶打開網(wǎng)站的過程,一步一步的走完整個(gè)流程。由于權(quán)限這塊邏輯還挺多,所以在添加了一個(gè)模塊來處理權(quán)限。

基于vuex, vue-router,vuex的權(quán)限控制教程,完整代碼地址見 https://github.com/linrunzhen...

接下來讓我們模擬一個(gè)普通用戶打開網(wǎng)站的過程,一步一步的走完整個(gè)流程。

首先從打開本地的服務(wù)localhost:8080開始,我們知道打開后會(huì)進(jìn)入login頁(yè)面,那么判斷的依據(jù)是什么。
首先是token。
沒有登陸的用戶是獲取不到token的,而登陸后的角色我們會(huì)將token存到local或者seesionStorage 因此,根據(jù)當(dāng)前有沒有token即可知道是否登陸。

為了存取token并且方便我們操作,可以配和vuex實(shí)現(xiàn)
/* state.js */
export default {
    get UserToken() {
        return localStorage.getItem("token")
    },
    set UserToken(value) {
        localStorage.setItem("token", value)
    }
}
/* mutation.js */
export default {
    LOGIN_IN(state, token) {
        state.UserToken = token
    },
    LOGIN_OUT(state) {
        state.UserToken = ""
    }
}
攔截的判斷

沒有token進(jìn)入需要權(quán)限的頁(yè)面:redirect到login頁(yè)面

由于我們路由是動(dòng)態(tài)掛載的,包括 " " 和404,所以當(dāng)匹配不到路由時(shí),也重定向到login

router.beforeEach((to, from, next) => {
    if (!store.state.UserToken) {
        if (
            to.matched.length > 0 &&
            !to.matched.some(record => record.meta.requiresAuth)
        ) {
            next()
        } else {
            next({ path: "/login" })
        }
    } 
})

好了,此時(shí)用戶打開localhost:8080,默認(rèn)匹配的是""路徑,此時(shí)我們并沒有掛載路由,也沒有token,所以來到了login。

輸入用戶名密碼后,有token了,通過store觸發(fā) commit("LOGIN_IN") 來設(shè)置token。

但是還是沒有路由,目前最開始只有l(wèi)ogin路由

/* 初始路由 */
export default new Router({
    routes: [
        {
            path: "/login",
            component: Login
        }
    ]
})

/* 準(zhǔn)備動(dòng)態(tài)添加的路由 */
export const DynamicRoutes = [
    {
        path: "",
        component: Layout,
        name: "container",
        redirect: "home",
        meta: {
            requiresAuth: true,
            name: "首頁(yè)"
        },
        children: [
            {
                path: "home",
                component: Home,
                name: "home",
                meta: {
                    name: "首頁(yè)"
                }
            }
        ]
    },
    {
        path: "/403",
        component: Forbidden
    },
    {
        path: "*",
        component: NotFound
    }
]
我們要根據(jù)當(dāng)前用戶的token去后臺(tái)獲取權(quán)限。

由于權(quán)限這塊邏輯還挺多,所以在vuex添加了一個(gè)permission模塊來處理權(quán)限。

為了判斷是已有路由列表,需要在vuex的permission模塊存一個(gè)state狀態(tài)permissionList用來判斷,假如permissionList不為null,即已經(jīng)有路由,如果不存在,就需要我們干活了。

router.beforeEach((to, from, next) => {
    if (!store.state.UserToken) {
        ...
    } else {
        /* 現(xiàn)在有token了 */
        if (!store.state.permission.permissionList) {
            /* 如果沒有permissionList,真正的工作開始了 */
            store.dispatch("permission/FETCH_PERMISSION").then(() => {
                next({ path: to.path })
            })
        } else {
            if (to.path !== "/login") {
                next()
            } else {
                next(from.fullPath)
            }
        }
    }
})

來看一下 store.dispatch("permission/FETCH_PERMISSION") 都干了什么

actions: {
    async FETCH_PERMISSION({ commit, state }) {
       /*  獲取后臺(tái)給的權(quán)限數(shù)組 */
        let permissionList = await fetchPermission()

        /*  根據(jù)后臺(tái)權(quán)限跟我們定義好的權(quán)限對(duì)比,篩選出對(duì)應(yīng)的路由并加入到path=""的children */
        let routes = recursionRouter(permissionList, dynamicRouter)
        let MainContainer = DynamicRoutes.find(v => v.path === "")
        let children = MainContainer.children
        children.push(...routes)

        /* 生成左側(cè)導(dǎo)航菜單 */
        commit("SET_MENU", children)

        setDefaultRoute([MainContainer])

        /*  初始路由 */
        let initialRoutes = router.options.routes

        /*  動(dòng)態(tài)添加路由 */
        router.addRoutes(DynamicRoutes)

        /* 完整的路由表 */
        commit("SET_PERMISSION", [...initialRoutes, ...DynamicRoutes])
    }
}
首先,await fetchPermission()獲取后臺(tái)給的權(quán)限數(shù)組,格式大概如下
{
    "code": 0,
    "message": "獲取權(quán)限成功",
    "data": [
        {
            "name": "訂單管理",
            "children": [
                {
                    "name": "訂單列表"
                },
                {
                    "name": "生產(chǎn)管理",
                    "children": [
                        {
                            "name": "生產(chǎn)列表"
                        }                     
                    ]
                },
                {
                    "name": "退貨管理"
                }
            ]
        }
    ]
}
其次根據(jù)我們寫好的路由數(shù)組,進(jìn)行對(duì)比,過濾得到我們要的路由
/* 這里是我們寫好的需要權(quán)限判斷的路由 */
const dynamicRoutes = [
    {
        path: "/order",
        component: Order,
        name: "order-manage",
        meta: {
            name: "訂單管理"
        },
        children: [
            {
                path: "list",
                name: "order-list",
                component: OrderList,
                meta: {
                    name: "訂單列表"
                }
            },
            {
                path: "product",
                name: "product-manage",
                component: ProductManage,
                meta: {
                    name: "生產(chǎn)管理"
                },
                children: [
                    {
                        path: "list",
                        name: "product-list",
                        component: ProductionList,
                        meta: {
                            name: "生產(chǎn)列表"
                        }
                    },
                    {
                        path: "review",
                        name: "review-manage",
                        component: ReviewManage,
                        meta: {
                            name: "審核管理"
                        }
                    }
                ]
            },
            {
                path: "returnGoods",
                name: "return-goods",
                component: ReturnGoods,
                meta: {
                    name: "退貨管理"
                }
            }
        ]
    }
]

export default dynamicRoutes

為了對(duì)比,我寫好了一個(gè)遞歸函數(shù),用name和meta.name進(jìn)行對(duì)比 ,根據(jù)這個(gè)函數(shù)就可以得到我們想要的結(jié)果

/**
 *
 * @param  {Array} userRouter 后臺(tái)返回的用戶權(quán)限json
 * @param  {Array} allRouter  前端配置好的所有動(dòng)態(tài)路由的集合
 * @return {Array} realRoutes 過濾后的路由
 */

export function recursionRouter(userRouter = [], allRouter = []) {
    var realRoutes = []
    allRouter.forEach((v, i) => {
        userRouter.forEach((item, index) => {
            if (item.name === v.meta.name) {
                if (item.children && item.children.length > 0) {
                    v.children = recursionRouter(item.children, v.children)
                }
                realRoutes.push(v)
            }
        })
    })
    return realRoutes
}

得到過濾后的數(shù)組后,加入到path為""的children下面

{
        path: "",
        component: Layout,
        name: "container",
        redirect: "home",
        meta: {
            requiresAuth: true,
            name: "首頁(yè)"
        },
        children: [
            {
                path: "home",
                component: Home,
                name: "home",
                meta: {
                    name: "首頁(yè)"
                }
            },
            
            ...
        ]
    }
這個(gè)時(shí)候,path為""的children就是我們左側(cè)的導(dǎo)航菜單了,存到state的sidebarMenu待用。加入到children后,這時(shí)DynamicRoutes就可以加入到路由了。
/*  動(dòng)態(tài)添加路由 */
router.addRoutes(DynamicRoutes)


 /*  初始路由 */
let initialRoutes = router.options.routes
/* 合并起來,就是完整的路由了 */
commit("SET_PERMISSION", [...initialRoutes, ...DynamicRoutes])
路由添加完了,也就是action操作完畢了,即可在action.then里面調(diào)用 next({ path: to.path })進(jìn)去路由,這里要注意, next里面要傳參數(shù)即要進(jìn)入的頁(yè)面的路由信息,因?yàn)閚ext傳參數(shù)后,當(dāng)前要進(jìn)入的路由會(huì)被廢止,轉(zhuǎn)而進(jìn)入?yún)?shù)對(duì)應(yīng)的路由,雖然是同一個(gè)路由,這么做主要是為了確保addRoutes生效了。
進(jìn)入路由后,要開始生成左側(cè)菜單,之前我們已經(jīng)存到sidebarMenu了,現(xiàn)在需要做的只是遞歸生成菜單而已,雖然用了element的導(dǎo)航菜單,但是為了遞歸路由,還需要自己封裝一下。這里核心的地方是組件的name,在組件里面有children的地方,又再次使用自己,從而遍歷整個(gè)tree結(jié)構(gòu)的路由。


刷新頁(yè)面后,根據(jù)我們r(jià)outer.beforeEach的判斷,有token但是沒permissionList,我們是會(huì)重新觸發(fā)action去獲取路由的,所以無需擔(dān)心。但是導(dǎo)航菜單active效果會(huì)不見。不過我們已經(jīng)把el-menu-item的key設(shè)置為路由的name,那么我們只要在刷新后,在afterEach把當(dāng)前路由的name賦值給el-menu default-active即可。同理,在afterEach階段獲取所有matched的路由,即可實(shí)現(xiàn)面包屑導(dǎo)航。
if (!store.state.permission.permissionList) {
    store.dispatch("permission/FETCH_PERMISSION").then(() => {
        next({ path: to.path })
    })
} 



...
router.afterEach((to, from, next) => {
    var routerList = to.matched
    store.commit("setCrumbList", routerList)
    store.commit("permission/SET_CURRENT_MENU", to.name)
})
退出登陸后,需要刷新頁(yè)面,因?yàn)槲覀兪峭ㄟ^addRoutes添加的,router沒有deleteRoutes這個(gè)api,所以清除token,清除permissionList等信息,刷新頁(yè)面是最保險(xiǎn)的。
最后還有一點(diǎn),每次請(qǐng)求得帶上token, 可以對(duì)axios封裝一下來處理
var instance = axios.create({
    timeout: 30000,
    baseURL
})

// 添加請(qǐng)求攔截器
instance.interceptors.request.use(
    function(config) {
        // 請(qǐng)求頭添加token
        if (store.state.UserToken) {
            config.headers.Authorization = store.state.UserToken
        }
        return config
    },
    function(error) {
        return Promise.reject(error)
    }
)

/* axios請(qǐng)求二次封裝 */
instance.get = function(url, data, options) {
    return new Promise((resolve, reject) => {
        axios
            .get(url, data, options)
            .then(
                res => {
                    var response = res.data
                    if (response.code === 0) {
                        resolve(response.data)
                    } else {
                        Message.warning(response.message)
                        /* reject(response.message) */
                    }
                },
                error => {
                    if (error.response.status === 401) {
                        Message.warning({
                            message: "登陸超時(shí),請(qǐng)重新登錄"
                        })
                        store.commit("LOGIN_OUT")
                        window.location.reload()
                    } else {
                        Message.error({
                            message: "系統(tǒng)異常"
                        })
                    }
                    reject(error)
                }
            )
            .catch(e => {
                console.log(e)
            })
    })
}

export default instance

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/107744.html

相關(guān)文章

  • 手摸手,帶你用vue擼后臺(tái) 系列二(登錄權(quán)限篇)

    摘要:我們將登錄按鈕上綁上事件,點(diǎn)擊登錄之后向服務(wù)端提交賬號(hào)和密碼進(jìn)行驗(yàn)證。所以前端和后端權(quán)限的劃分是不太一致。側(cè)邊欄最后一個(gè)涉及到權(quán)限的地方就是側(cè)邊欄,不過在前 完整項(xiàng)目地址:vue-element-admin 系列文章: 手摸手,帶你用vue擼后臺(tái) 系列一(基礎(chǔ)篇) 手摸手,帶你用vue擼后臺(tái) 系列二(登錄權(quán)限篇) 手摸手,帶你用vue擼后臺(tái) 系列三 (實(shí)戰(zhàn)篇) 手摸手,帶你用vu...

    不知名網(wǎng)友 評(píng)論0 收藏0
  • vue中如何實(shí)現(xiàn)后臺(tái)管理系統(tǒng)的權(quán)限控制

    摘要:二接口訪問的權(quán)限控制接口權(quán)限就是對(duì)用戶的校驗(yàn)。代碼如下按扭權(quán)限指令至此為止,權(quán)限控制流程就已經(jīng)完全結(jié)束了,在最后我們?cè)倏匆幌峦暾臋?quán)限控制流程圖吧五路由控制完整流程圖六參考文獻(xiàn)手?jǐn)]后臺(tái)管理網(wǎng)站之權(quán)限控制手摸手,帶你用擼后臺(tái)之權(quán)限控制 原文首發(fā)于我的博客,歡迎點(diǎn)擊查看獲得更好的閱讀體驗(yàn)~ 一、前言 在廣告機(jī)項(xiàng)目中,角色的權(quán)限管理是卡了挺久的一個(gè)難點(diǎn)。首先我們確定的權(quán)限控制分為兩大部分,其...

    songze 評(píng)論0 收藏0
  • vue中如何實(shí)現(xiàn)后臺(tái)管理系統(tǒng)的權(quán)限控制

    摘要:二接口訪問的權(quán)限控制接口權(quán)限就是對(duì)用戶的校驗(yàn)。代碼如下按扭權(quán)限指令至此為止,權(quán)限控制流程就已經(jīng)完全結(jié)束了,在最后我們?cè)倏匆幌峦暾臋?quán)限控制流程圖吧五路由控制完整流程圖六參考文獻(xiàn)手?jǐn)]后臺(tái)管理網(wǎng)站之權(quán)限控制手摸手,帶你用擼后臺(tái)之權(quán)限控制 原文首發(fā)于我的博客,歡迎點(diǎn)擊查看獲得更好的閱讀體驗(yàn)~ 一、前言 在廣告機(jī)項(xiàng)目中,角色的權(quán)限管理是卡了挺久的一個(gè)難點(diǎn)。首先我們確定的權(quán)限控制分為兩大部分,其...

    iliyaku 評(píng)論0 收藏0
  • vue中如何實(shí)現(xiàn)后臺(tái)管理系統(tǒng)的權(quán)限控制

    摘要:二接口訪問的權(quán)限控制接口權(quán)限就是對(duì)用戶的校驗(yàn)。代碼如下按扭權(quán)限指令至此為止,權(quán)限控制流程就已經(jīng)完全結(jié)束了,在最后我們?cè)倏匆幌峦暾臋?quán)限控制流程圖吧五路由控制完整流程圖六參考文獻(xiàn)手?jǐn)]后臺(tái)管理網(wǎng)站之權(quán)限控制手摸手,帶你用擼后臺(tái)之權(quán)限控制 原文首發(fā)于我的博客,歡迎點(diǎn)擊查看獲得更好的閱讀體驗(yàn)~ 一、前言 在廣告機(jī)項(xiàng)目中,角色的權(quán)限管理是卡了挺久的一個(gè)難點(diǎn)。首先我們確定的權(quán)限控制分為兩大部分,其...

    VincentFF 評(píng)論0 收藏0
  • addRoutes爬坑記

    摘要:簡(jiǎn)介用動(dòng)態(tài)路由實(shí)現(xiàn)權(quán)限控制,是一個(gè)很的方案不是么初始路由只有登錄頁(yè),根據(jù)用戶的查詢對(duì)應(yīng)的權(quán)限,然后,將獲取到的菜單數(shù)據(jù)放入和瀏覽器緩存中。 addRoutes簡(jiǎn)介 用動(dòng)態(tài)路由實(shí)現(xiàn)權(quán)限控制,是一個(gè)很nice的方案不是么? 初始路由只有登錄頁(yè),根據(jù)用戶的id查詢對(duì)應(yīng)的權(quán)限,然后addRoutes,將獲取到的菜單數(shù)據(jù)放入vuex和瀏覽器緩存中。 動(dòng)態(tài)添加更多的路由規(guī)則。參數(shù)必須是一個(gè)符合 r...

    draveness 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<