序文:最近、プロジェクトで管理システムに遭遇しました。権限設定が非常に興味深いと思いました。自分の学習を容易にし、考えを整理するために、プロセスの実装プロセスを記録しました。考えの一部は、コードのコメントに統合されています。 ルーティング傍受認証の2つの一般的な方法1: ルートインターセプション: ルートにフィールド識別子を追加し、ルートインターセプションを通じて実装するだけです 比較する:ルートインターセプションの実装は比較的簡単です。router.beforeEach 内のページをルート設定情報に従ってフィルタリングし、コンポーネントに移動する権限があるかどうかを確認するだけです。対応する権限が不十分な場合は、対応するコンポーネントに移動しません。 動的ルーティングは実装が比較的複雑で、バックエンドの協力が必要です。本質的には、ルーティング構成テーブルは 2 つの部分に分かれています。異なるユーザーがログインすると、ルーティング構成テーブルはユーザーの権限情報に基づいてフィルタリングされ、ユーザーが追加する権限を持たない部分はレンダリングされません。比較的大規模なバックエンド システムに適しています。 注: この記事では主に動的ルーティング認証の実装について紹介します 次のファイルは通常、動的ルーティングに関連しています。
ルータ router.js のルーティング設定テーブルは、パブリックルーティングと動的パーミッションルーティングの 2 つの部分に分けられます。動的パーミッションルーティングはフロントエンドに配置できます。認証時に、フロントエンドが配列を独自にフィルタリングすることも、バックエンドに配置してフィルタリングすることもできます。考え方は同じです。以下では、フロントエンドに配置される設定テーブルについて説明します。 デフォルトの新しいルーターをエクスポートします({ ルート: { パス:'/login', 名前:'ログイン', コンポーネント:aa }, { パス: '/home', 名前:'ホーム', コンポーネント:cc }, ] }) 上記は一般的なプロジェクトのルーティング設定です。ここで認証を行う必要があるため、ルーティング設定テーブルを次の 2 つの配列に少し分割する必要があります。 'vue' から Vue をインポートします 'vue-router' から Router をインポートします。 Vue.use(ルーター) export const defaultRoute = [ //固定部分権限の配列、すべてのユーザーがアクセスできるルート { パス:'/login', コンポーネント:aa }, ] export const asyncRoute = [ //動的に構成されたルーティングテーブル。動作する前にフィルタリングする必要があります { パス:'/order', 名前:'注文', コンポーネント:aa、 メタ:{ システム:'注文' } } { パス:'/roles', 名前:'役割', コンポーネント:aa、 メタ:{ システム:'役割' } } ] //ルーティングテーブルを登録 const createRouter = () => new Router({ // モード: 'history'、// サービスサポートが必要 スクロール動作: () => ({ y: 0 }), ルート: 定数ルート }) 定数ルーター = createRouter() //ルーティングワークシートをリセットします。このメソッドはログアウト時に呼び出す必要があります。export function resetRouter() { 定数 newRouter = createRouter() router.matcher = 新しいRouter.matcher } デフォルトルーターをエクスポートする permission.js権限ファイルは、主にグローバル ルーティングのインターセプトと、ユーザー権限に応じたルーティングの動的フィルタリングに使用されます。この部分には、動的ルーティングをいつ処理するか、どのような条件でルーティングを処理するかという 2 つの問題が主に関係します。 './router' からルーターをインポートします './store' からストアをインポートします import { getToken } from '@/utils/auth' // トークンにアクセスするためのカスタムカプセル化メソッド Route.beforeEach((to,from,next) =>{ // ユーザーがログインしているかどうかを判断するためのトークンを取得します。const hasToken = getToken() トークンがある場合 //ユーザーがログインしたかどうかを判断します if (to.path === "/login") { /** *ユーザーはログインしていますが、ログインページにルーティングされます。これは、ユーザーがログアウト操作を実行したことを意味します。そのため、この場所でトークンをクリアするか、カスタムロジックを記述することができます。*/ 次() }それ以外{ /** *ここでは、ユーザーがログインしているかログイン ボタンをクリックした場合、トークンはローカル ストレージに保存されていますが、ログインにルーティングされていません。/login へのルートがない場合は、そのままにしておきます。ここでいくつかの処理を行います。つまり、ユーザーがログインして直接解放できるため、解放する前に、ここでいくつかのロジックを実行する必要があります。つまり、ユーザーの権限を判断し、動的に構成されたルーティング テーブルで、ユーザーの権限に基づいて権限を満たすルートをフィルター処理し、それらをルーティング構成テーブルに挿入して使用します。* * ここで、2 つの問題が関係します。 *1: 動的ルーティングを処理するタイミング(ログイン後、ホームページに入る前、つまり*次へ進む前) *2: 動的ルーティングを処理する条件 */ /** *ここで、まずストア内のユーザー権限リストの長さが 0 かどうかを確認できます。長さが 0 の場合、ユーザーはログイン ボタンをクリックしただけで、ページに入っていないことを意味します。このとき、権限フィルタリングを行う必要があります。 *長さが0でない場合は、認証プロセスが正常であることを意味します。対応するコンポーネントに直接移動してください。 *この手順は主に、配列の繰り返しフィルタリングを防ぎ、パフォーマンスを節約するためのものです。 */ store.getters.roles.length > 0 の場合 { 次() }それ以外{ //コードがこの時点に到達した場合、ユーザーはログインしていることを意味します。認証プロセスはまだ開始されていません。 //ここで認証プロセスを実行する必要があります store.dispatch('getRoles').then(res=>{ // ここでの res は、3 番目のステップの peomise の解決です // これは権限情報の配列です store.dispatch('createRouters',res.data) .then(res=>{ // これは、ストアを呼び出して動的ルートを作成する関数です。この関数に // 権限配列を渡すことも、ここで渡すこともできます。 // この関数は、同じ方法で状態内のロールの値を直接取得します。 let addRouters = store.getters('addRouters') allRouters を store.getters('allRouters') にします。 // 動的ルーティング部分を作業ルートに追加します router.addRoutes(accessRoutes) // インターセプトされたページに移動します next({ ...to, replace: true }) }) }) } } } それ以外 { /** ここでは、トークンがない、つまりユーザーがこの時点でログインしていない状況を処理します。ログインしているユーザーがいない場合は、ユーザーがログイン ページに行くかどうかを判断します。ログイン ページの場合は、直接アクセスします。ユーザーがログインせずにホームページにアクセスしたい場合は、ログイン ページにリダイレクトします。*/ to.path == '/login'の場合{ //この場所はもっと慎重に判断できます。ログイン時に直接行かせる必要はありませんが、 //すべてのパブリックコンポーネントに行くときは、直接次に行かせます() }それ以外{ 次へ('/ログイン') } } })
ストア // api フォルダーでユーザーの権限を取得するためのインターフェースを定義し、このアクションで呼び出しますimport { getUserRole } from "../api/getRoles" // 権限を取得するためのインターフェースimport { logout } from '../api/user' // ユーザー ログアウトのためのインターフェースimport { resetRouter } from './router' import { removeToken } from '@/utils/auth' // トークンをクリアするためのカスタムカプセル化メソッド // これは配列をフィルタリングするメソッドです。ルーティングテーブルが複数のレイヤーにネストされている場合は、このメソッドを再帰的に呼び出して配列をフィルタリングできます //function hasPermission(roles, route) { // (route.meta && route.meta.roles) の場合 { // roles.some(role => route.meta.roles.includes(role)) を返します // } それ以外 { // true を返す // } // //関数 filterAsyncRoutes(routes, roles) をエクスポートします。 // 定数 res = [] // ルート.forEach(ルート => { // const tmp = { ...ルート } // if (hasPermission(roles, tmp)) { // if (tmp.children) { // tmp.children = filterAsyncRoutes(tmp.children, ロール) // } // res.push(tmp) // } // }) // // resを返す // // デフォルトルーティングと動的ルーティングを導入する import { defaultRoute , asyncRouter } from '@/router' 定数状態 = { roles: [] //インターフェースによって取得される権限リスト。データ形式は次の通り: ["order", "roles"], allRouters: [], //これはすべての統合後の最終的な作業ルートです addRouters: [], //これは権限の動的な一致に従ってフィルタリングされたルートです} const ゲッター = { /** このゲッター内の状態の役割を保存し、このゲッター内の役割を取得する他の場所では、元の役割が変更される限り、他の場所の役割も変更されます。これは、計算されたプロパティと同等です */ ロール:状態 => 状態.ロール allRouters:状態 => 状態.allRouters addRouters:state => state.addRouters } const 変異: { /**次のアクションでは、権限情報の配列をコミットを通じてこの場所に送信し、*この場所は配列を状態のロールに送信します */ SetRoute(状態、ルーター) //ここでのルーターは、ユーザー権限に応じてフィルタリングされたルーティングテーブルです。state.allRouters = defaultRoute.concat(router) state.addRouters = ルーター } //ルーティング許可配列を状態に保存する setRoles(状態、値){ 状態.役割 = 値 } } 定数アクション: { //現在ログインしているロールの権限を取得するリクエストを記述します。例: ["/order","roles"]。リクエストがこのように返された場合、このロールの権限は order ルートと roles ルートへのアクセスであることを意味します。 // 権限情報を取得する状況は 2 つ考えられます。ただし、次の権限情報は別のインターフェイスです。 // 権限情報は、ユーザーログインインターフェースと一緒に返される場合もあります // 現在のユーザーの権限情報を取得し、状態に格納します。この権限情報は、バックエンドと通信される場合があります // リクエストするための別のインターフェースとして記述されることはありません。代わりに、ログインすると、ユーザー情報とユーザーの権限情報が一度に返されます。その後、ユーザーがログインすると、権限情報が状態に格納されます。 // 目的は、権限情報の配列を状態に格納することです。 // ロールの権限を取得するメソッド getRoles({commit},data){ 新しいPromise(resolve,reject)を返す{ // ユーザー権限を取得するには、インターフェイス getUserRole() を呼び出します。その後 (res =>{ //ここで返されるデータは、次のような権限情報の配列である必要があります: ["order", "roles"] //ミューテーションを通じて権限情報を状態に保存する コミット('setRoles',res.data) 解決(res.data) }) } }) //権限に基づいて配列構成テーブルをフィルタリングするメソッド createRouters({ commit } , data ){ 新しい Promise を返します ((resolve,reject) => { addRouters = [ ] とします if (data.includes("admin") { 追加ルーター = 非同期ルーター }それ以外{ // プロジェクト開発では、ルーティング配列が複数のレイヤーにネストされる可能性があるため、この場所では上記のカスタムメソッドを使用する必要があります // 再帰的にフィルタリングするメソッド。このデモでは配列の 1 つのレイヤーのみを処理します //(filterAsyncRoutes) メソッド addRouters = asyncRouter.filter(item=>{ if (data.includes(item.meta.system) ) { 返品商品 } }) } //一致した権限ルートをmutationsに渡し、mutationsを //一致したルートを状態に保存する コミットします。("SetRoute",addRouters) resolve() //ここでresolveを呼び出す必要があります。これにより、外部のユーザーは、//.thenを通じて配列フィルタリングが成功したというコールバックを取得できます。}) }, ログアウト({コミット}){ 新しい Promise を返します ((resolve, reject) => { ログアウト().then(() => { removeToken() // 最初にトークンを削除する必要があります ルータをリセットする() コミット('setRoles', []) コミット('SetRoute', []) 解決する() }).catch(エラー => { 拒否(エラー) }) }) }, } エクスポートデフォルト{ 州、 ゲッター、 突然変異、 アクション } ログアウト: 非同期関数logout(){ 試す{ const res = store.dispatch.logout() を待機します (res.code == 200){ //ログアウト成功 } }キャッチ{ //ログアウトに失敗しました(エラー) } } エンディング:コードはたくさんありますが、考え方は非常にシンプルで、ルーティング構成テーブルを取得し、配列をフィルタリングして動的に追加するだけです。 プロジェクトリファレンス github: vue-element-admin これで、vue要素のバックグラウンド認証プロセスの分析に関するこの記事は終了です。より関連性の高いvue要素認証コンテンツについては、123WORDPRESS.COMで以前の記事を検索するか、次の関連記事を引き続き閲覧してください。今後とも123WORDPRESS.COMを応援してください。 以下もご興味があるかもしれません:
|
<<: lnmp を使用して MySQL データベースのルート パスワードをリセットする 2 つの方法
>>: Linuxカーネルマクロcontainer_ofの詳細な分析
任意のウェブページを開きます。例: http://www.baidu.com/ ブラウザのタブのヘッ...
序文<router-link> タグは、Vue アプリ内のさまざまなページ間を移動するた...
インストールパス: /application/mysql-5.5.56 1. 事前準備MySQL 依...
目次序文リスナーと計算プロパティの違いvue3 で watch を使用するにはどうすればいいですか?...
この記事では、ウォーターフォールフローが底に達したときにデータを動的にロードするためのjsの具体的な...
Java開発キットjdkをダウンロードするJDK のダウンロード アドレスはhttp://www.o...
公式の MySQL イメージを使用するには、構成ファイル、DB データ ファイル ディレクトリなどの...
設置環境1. gccのインストールnginxをインストールするには、まず公式サイトからダウンロードし...
今日、Apache の nginx リバース プロキシを実行していたときに、ちょっとした問題に遭遇し...
この機能を実装するにあたり、本家ブロガーさんから拝借した方法では色の切り替えが実現できず、長い間考え...
目次1. 基本的なイベント処理2. 親コンポーネントにカスタムイベントを送信するマウス修飾子4. キ...
成果を達成する実装コードhtml <ヘッダー> <h1><em>...
以下の操作デモンストレーションはすべて MySQL バージョン 5.6.36 に基づいています。仕事...
公式文書には次のように記されている。ルーターを挿入することで、どのコンポーネントでも this.$r...
目次1. はじめに2. 導入環境ツール4. 展開プロセス要約する1. はじめにNextcloud は...