Vueルート権限制御解析
前言
本人は会社で主に中楽屋システムの開発を担当しています。ルートと権限検査はとても重要で、最も基本的な一環です。実際の開発プロジェクトでは、ログインとルート権限の制御について、vue-element-adminというスタープロジェクトを参照して、それに基づいて業務を統合しました。これからはこのプロジェクトを例にして、ルート全体と権限検査の過程を詳しく分析します。
プロジェクト全体のディレクトリ構造
今日のテーマに入る前に、まずプロジェクト全体を整理します。 api:インターフェース要求 クラスets:静的資源 components:汎用コンポーネント directive:カスタムコマンド filters:カスタムフィルタ icons:アイコン layout:レイアウトコンポーネント(ページアーキテクチャコア) router:ルーティング構成(ルーティング権限コアモジュール) store:状態管理 スタイルファイル utils:ツール方法 view:ページコンポーネント permission.js権限管理 このプロジェクトに興味がある人は自分で勉強してもいいです。ルートの権限検査の機能以外にも面白い機能がたくさん含まれています。多くのことを学ぶことができると信じています。
ルート権限制御ロジック
ルーティング処理フローチャート
ルート処理のソースコード分析
私たちはまずpermission.jsファイルを見つけました。ここではグローバルルーティング・ガードを定義します。ルート権限の中で非常に重要なコアコードです。みんなが読みやすいように、ルートに関するコードだけを外しました。
まずルートの定義を見てみます。/src/router/index.jsファイルの下です。
ルーティング論理図を動的に追加
動的ルートのソースコード分析
コードエントリ:permission.js
ルート権限制御の基本的な流れはすでに分析済みです。これからはプロジェクトのボタン権限制御の実現を見に来ます。実現も簡単です。
存在する
ユーザキャラクター情報が存在すると、そのユーザの最終的なアクセス可能なルートが生成されたことを説明し、直接に実行することができる。
ユーザ情報が存在しません。
1.ユーザ情報インターフェースを呼び出し、ユーザ情報を取得し、ユーザ情報をvuexに保存する。
2.ユーザーの役割を判断する管理者であれば、すべてのモジュールにアクセス権限を持つ 。非管理者は、非同期的なルーティングをスクリーニングする必要があり、非同期的なルーティングを介して、Meta.rolesを介してユーザ情報と比較し、ユーザがアクセス権限を持っているかどうか判断する 。
3.最終的なアクセス可能なルーティングをvuexに保存し、最後にrouter.addRoutesを通じて最終的なルーティング構成リストを統合する。
tokenは存在しません
アクセスルートがホワイトリストであれば、直接にアクセスします。
アクセスルートに白いリストが存在しない場合は、ログインページのpath:/login?redirect=/xxxにリダイレクトし、ログインが成功したら/xxxに対応するページにジャンプします。
以上がVueルートの権限制御解析の詳細です。Vueルートの権限制御に関する資料は他の関連記事に注目してください。
本人は会社で主に中楽屋システムの開発を担当しています。ルートと権限検査はとても重要で、最も基本的な一環です。実際の開発プロジェクトでは、ログインとルート権限の制御について、vue-element-adminというスタープロジェクトを参照して、それに基づいて業務を統合しました。これからはこのプロジェクトを例にして、ルート全体と権限検査の過程を詳しく分析します。
プロジェクト全体のディレクトリ構造
今日のテーマに入る前に、まずプロジェクト全体を整理します。
ルート権限制御ロジック
ルーティング処理フローチャート
ルート処理のソースコード分析
私たちはまずpermission.jsファイルを見つけました。ここではグローバルルーティング・ガードを定義します。ルート権限の中で非常に重要なコアコードです。みんなが読みやすいように、ルートに関するコードだけを外しました。
import router from './router'
import store from './store'
import { Message } from 'element-ui'
import NProgress from 'nprogress' // progress bar
import 'nprogress/nprogress.css' // progress bar style
import { getToken } from '@/utils/auth' // get token from cookie
NProgress.configure({ showSpinner: false }) // NProgress Configuration
const whiteList = ['/login', '/auth-redirect'] //
router.beforeEach(async(to, from, next) => {
// start progress bar
NProgress.start()
// token
if (hasToken) {
if (to.path === '/login')
// /login,
next({ path: '/' })
NProgress.done() // hack: https://github.com/PanJiaChen/vue-element-admin/pull/2939
} else {
// determine whether the user has obtained his permission roles through getInfo
const hasRoles = store.getters.roles && store.getters.roles.length > 0
if (hasRoles) {
next()
} else {
try {
//
const { roles } = await store.dispatch('user/getInfo')
// ,
const accessRoutes = await store.dispatch('permission/generateRoutes', roles)
// ( )
router.addRoutes(accessRoutes)
//
next({ ...to, replace: true })
} catch (error) {
// token
await store.dispatch('user/resetToken')
Message.error(error || 'Has Error')
//
next(`/login?redirect=${to.path}`)
NProgress.done()
}
}
}
} else {
// token
if (whiteList.indexOf(to.path) !== -1) {
// , ,
next()
} else {
// , .
next(`/login?redirect=${to.path}`)
NProgress.done()
}
}
})
router.afterEach(() => {
// finish progress bar
NProgress.done()
})
コードの中の/login?redirect=$jt.path、ここでのredirectパラメータは主にユーザ登録成功後にジャンプするためのページパスです。具体的な機能は/view/login/index.vueファイルの下にあります。
watch: {
$route: {
handler: function(route) {
const query = route.query
if (query) { //
this.redirect = query.redirect
this.otherQuery = this.getOtherQuery(query)
}
},
immediate: true
}
},
// methods :
handleLogin() { //
this.$refs.loginForm.validate(valid => {
if (valid) { //
this.$store.dispatch('user/login', this.loginForm)
.then(() => {
// this.redirect
this.$router.push({ path: this.redirect || '/', query: this.otherQuery })
this.loading = false
})
} else {
// ..
}
})
},
動的経路設定まずルートの定義を見てみます。/src/router/index.jsファイルの下です。
export const constantRoutes = [ // ,
//
]
export const asyncRoutes = [ // meta.roles ,
{
path: '/permission',
component: Layout,
redirect: '/permission/page',
alwaysShow: true, // will always show the root menu
name: 'Permission',
meta: {
title: 'Permission',
icon: 'lock',
roles: ['admin', 'editor'] // roles
},
// ...
}
]
動的にルートを追加する場合、基本的にはユーザーの役割情報に基づいてasyncRoutesルート構成配列にルートフィルタをかけ、対応するルートを見つけ、constantRoutesと統合して最新のルートを生成する。ルーティング論理図を動的に追加
動的ルートのソースコード分析
コードエントリ:permission.js
const accessRoutes = await store.dispatch('permission/generateRoutes', roles)
permission/generate Routes方法入口ファイル:/store/modules/permissions.js
import { asyncRoutes, constantRoutes } from '@/router'
const state = {
routes: [],
addRoutes: []
}
const mutations = {
SET_ROUTES: (state, routes) => {
state.addRoutes = routes
state.routes = constantRoutes.concat(routes)
}
}
const actions = {
generateRoutes({ commit }, roles) {
return new Promise(resolve => {
let accessedRoutes
if (roles.includes('admin')) {
// admin, admin,
accessedRoutes = asyncRoutes || []
} else {
// , roles
accessedRoutes = filterAsyncRoutes(asyncRoutes, roles)
}
// vuex
commit('SET_ROUTES', accessedRoutes)
// resolve
resolve(accessedRoutes)
})
}
}
非同期ルートをスクリーニングし、最終的な結果をvuexに保存し、結果のresoveを外に出します。
export function hasPermission(roles, route) {
if (route.meta && route.meta.roles) { // meta.roles
// meta.roles ,
return roles.some(role => route.meta.roles.includes(role))
} else {
// meta meta.roles, ,
return true
}
}
export function filterAsyncRoutes(routes, roles) {
const res = []
routes.forEach(route => {
const tmp = { ...route }
if (hasPermission(roles, tmp)) { //
if (tmp.children) {
// children,
tmp.children = filterAsyncRoutes(tmp.children, roles)
}
// res
res.push(tmp)
}
})
return res
}
最後に/permission.jsファイルに戻ります。
const accessRoutes = await store.dispatch('permission/generateRoutes', roles)
// accessRoutes ,
// route.addRoutes constRoutes accessRoutes ,
router.addRoutes(accessRoutes)
拡張→ボタンの権限ルート権限制御の基本的な流れはすでに分析済みです。これからはプロジェクトのボタン権限制御の実現を見に来ます。実現も簡単です。
<div v-permission="['admin','editor']"></div>
import store from '@/store'
function checkPermission(el, binding) {
const { value } = binding
// store ,
const roles = store.getters && store.getters.roles
if (value && value instanceof Array) { // ,
if (value.length > 0) {
const permissionRoles = value
// permissionRoles , roles ,
const hasPermission = roles.some(role => {
return permissionRoles.includes(role)
})
// , 。
// v-permission
if (!hasPermission) {
el.parentNode && el.parentNode.removeChild(el)
}
}
} else {
throw new Error(`need roles! Like v-permission="['admin','editor']"`)
}
}
export default {
inserted(el, binding) {
checkPermission(el, binding)
},
update(el, binding) {
checkPermission(el, binding)
}
}
締め括りをつける存在する
ユーザキャラクター情報が存在すると、そのユーザの最終的なアクセス可能なルートが生成されたことを説明し、直接に実行することができる。
ユーザ情報が存在しません。
1.ユーザ情報インターフェースを呼び出し、ユーザ情報を取得し、ユーザ情報をvuexに保存する。
2.ユーザーの役割を判断する
3.最終的なアクセス可能なルーティングをvuexに保存し、最後にrouter.addRoutesを通じて最終的なルーティング構成リストを統合する。
tokenは存在しません
アクセスルートがホワイトリストであれば、直接にアクセスします。
アクセスルートに白いリストが存在しない場合は、ログインページのpath:/login?redirect=/xxxにリダイレクトし、ログインが成功したら/xxxに対応するページにジャンプします。
以上がVueルートの権限制御解析の詳細です。Vueルートの権限制御に関する資料は他の関連記事に注目してください。