1. 程式人生 > 程式設計 >使用React-Router實現前端路由鑑權的示例程式碼

使用React-Router實現前端路由鑑權的示例程式碼

React-Router 是React生態裡面很重要的一環,現在React的單頁應用的路由基本都是前端自己管理的,而不像以前是後端路由,React管理路由的庫常用的就是就是 React-Router 。本文想寫一下 React-Router 的使用,但是光介紹API又太平淡了, 而且官方文件已經寫得很好了 ,我這裡就用一個常見的開發場景來看看 React-Router 是怎麼用的吧。而我們一般的系統都會有使用者訪問許可權的限制,某些頁面可能需要使用者具有一定的許可權才能訪問。本文就是用 React-Router 來實現一個前端鑑權模型。

本文全部程式碼已經上傳GitHub,大家可以拿下來玩玩:https://github.com/dennis-jiang/Front-End-Knowledges/tree/master/Examples/React/react-router-usage

應用示例

本文要實現的功能是大家經常遇到的場景,就是要控制不同的使用者角色來訪問不同的頁面,這裡總共有四個頁面:

  • /index: 網站首頁
  • /login: 登入頁
  • /backend:後臺頁面
  • /admin:管理頁面

另外還有三種角色:

  • 未登入使用者:只能訪問網站首頁/index和登入頁/login
  • 普通使用者:可以訪問網站首頁/index,登入頁/login和後臺頁面/backend
  • 管理員:可以訪問管理頁面/admin和其他所有頁面

引入React-Router

要實現路由鑑權,我們還得一步一步來,我們先用React-Router搭建一個簡單的帶有這幾個頁面的專案。我們直接用 create-react-app

建立一個新專案,然後建了一個 pages 資料夾,裡面放入我們前面說的那幾個頁面:

使用React-Router實現前端路由鑑權的示例程式碼

我們頁面先寫簡單點,先寫個標題吧,比如這樣:

import React from 'react';

function Admin() {
 return (
 <h1>管理員頁面</h1>
 );
}

其他幾個頁面也是類似的。

然後我們就可以在 App.js 裡面引入 React-Router 做路由跳轉了,注意我們在瀏覽器上使用的是 react-router-dom ,新版的 React-Router 將核心邏輯層和展示層分開了,核心邏輯會處理路由匹配等,展示層會處理實際的跳轉和路由變化的監聽,之所以這麼分,是因為React-Router不僅僅需要支援瀏覽器,還需要支援React Native,這兩個平臺的監聽和跳轉是不一樣的,所以現在 React-Router 下面有好幾個包了:

  • react-router :核心邏輯處理,提供一些公用的基類
  • react-router-dom :具體實現瀏覽器相關的路由監聽和跳轉
  • react-router-native :具體實現RN相關的路由監聽和跳轉

在實際使用時,我們一般不需要引用 react-router ,而是直接用 react-router-dom 就行,因為它自己會去引用 react-router 。下面我們在專案裡面引入 react-router-dom

import React from 'react';
import {
 BrowserRouter as Router,Switch,Route,} from "react-router-dom";
import Home from './pages/Home';
import Login from './pages/Login';
import Backend from './pages/Backend';
import Admin from './pages/Admin';

function App() {
 return (
 <Router>
  <Switch>
  <Route path="/login" component={Login}/>
  <Route path="/backend" component={Backend}/>
  <Route path="/admin" component={Admin}/>
  <Route path="/" component={Home}/>
  </Switch>
 </Router>
 );
}

export default App;

然後可以在 Home 頁面用 Link 加上跳轉到其他頁面的連結,這樣就可以跳轉了:

import React from 'react';
import { Link } from 'react-router-dom';

function Home() {
 return (
 <>
  <h1>首頁</h1>
  <ul>
  <li><Link to="/login">登入</Link></li>
  <li><Link to="/backend">後臺</Link></li>
  <li><Link to="/admin">管理員</Link></li>
  </ul>
 </>
 );
}

export default Home;

到現在我們的應用執行起來是這樣的:

使用React-Router實現前端路由鑑權的示例程式碼

模組劃分

雖然我們的跳轉實現了,但是所有人都可以訪問任何頁面,我們前面的需求是要根據登入的角色限制訪問的頁面的,在寫程式碼前,我們先來思考下應該怎麼做這個。當然最直觀最簡單的方法就是每個頁面都檢測下當前使用者的角色,匹配不上就報錯或者跳回首頁。我們現在只有幾個頁面,這樣做好像也還好,但是如果我們的應用變大了,頁面變多了,每個頁面都來一次檢測就顯得很重複了,所以我們應該換個角度來思考這個問題。

仔細一看,其實我們總共就三種角色,對應三種不同的許可權,這三個許可權還有層級關係,高級別的許可權包含了低級別的許可權,所以我們的頁面也可以按照這些許可權分為三種:

  • 公共頁面:所有人都可以訪問,沒登入也可以訪問,包括網站首頁和登入頁
  • 普通頁面:普通登入使用者可以訪問的頁面
  • 管理員頁面:只有管理員才能訪問的頁面

為了好管理這三種頁面,我們可以將他們抽取成三個檔案,放到一個獨立的資料夾 routes 裡面,三個檔案分別命名為 publicRoutes.jsprivateRoutes.jsadminRoutes.js

使用React-Router實現前端路由鑑權的示例程式碼

對於每個路由檔案,我們可以將這類路由組織成陣列,然後 export 出去給外面呼叫,比如 publicRoutes.js

import Login from '../pages';
import Home from '../pages/Home';

const publicRoutes = [
 {
 path: '/login',component: Login,exact: true,},{
 path: '/',component: Home,];

export default publicRoutes;

然後我們外面使用的地方直接改為:

import publicRoutes from './routes/publicRoutes';

function App() {
 return (
 <Router>
  <Switch>
  {publicRoutes.map(
   ({path,component,...routes}) => 
   <Route key={path} path={path} component={component} {...routes}/>
  )}
  <Route path="/backend" component={Backend}/>
  <Route path="/admin" component={Admin}/>
  </Switch>
 </Router>
 );
}

這樣我們的 App.js 裡面就不會有冗長的路由路由列表了,而是隻需要迴圈一個數組就行了。但是對於需要登入才能訪問的頁面和管理員頁面我們不能直接渲染 Route 元件,我們最好再封裝一個高階元件,將鑑權的工作放到這個元件裡面去,這樣我們普通的頁面在實現時就不需要關心怎麼鑑權了。

封裝高階元件

要封裝這個鑑權元件思路也很簡單,前面我們將 publicRoutes 直接拿來迴圈渲染了 Route 元件,我們的鑑權元件只需要在這個基礎上再加一個邏輯就行了:在渲染真正的 Route 元件前先檢查一下當前使用者是否有對應的許可權,如果有就直接渲染 Route 元件,如果沒有就返回某個頁面,可以是登入頁或者後臺首頁,具體根據自己專案需求來。所以我們的路由配置檔案 privateRoutes.jsadminRoutes.js 裡面的路由會比 publicRoutes.js 的多兩個引數:

// privateRoutes.js
import Backend from '../pages/Backend';

const privateRoutes = [
 {
 path: '/backend',component: Backend,role: 'user',// 當前路由需要的角色許可權
 backUrl: '/login' // 不滿足許可權跳轉的路由
 },];

export default privateRoutes;

adminRoutes.js 是類似的寫法:

// adminRoutes.js
import Admin from '../pages/Admin';

const adminRoutes = [
 {
 path: '/admin',component: Admin,role: 'admin',// 需要的許可權是admin
 backUrl: '/backend' // 不滿足許可權跳回後臺頁面
 },];

export default adminRoutes;

然後就可以寫我們的高階元件了,我們將它命名為 AuthRoute 吧,注意我們這裡假設的使用者登入時後端API會返回給我們當前使用者的角色,一個使用者可能有多個角色,比如普通使用者的角色是 ['user'] ,管理員的角色是 ['user','admin'] ,具體的許可權驗證邏輯要看自己專案許可權的設計,這裡只是一個例子:

// AuthRoute.js
import React from 'react';
import { Route,Redirect } from 'react-router-dom';

function AuthRoute(props) {
 const {
 user: {
  role: userRole
 },role: routeRole,backUrl,...otherProps
 } = props;

 // 如果使用者有許可權,就渲染對應的路由
 if (userRole && userRole.indexOf(routeRole) > -1) {
 return <Route {...otherProps} />
 } else {
 // 如果沒有許可權,返回配置的預設路由
 return <Redirect to={backUrl} />
 }
}

export default AuthRoute;

然後用我們的 AuthRoute 的渲染 adminRoutesprivateRoutes :

// ... 省略其他程式碼 ...

{privateRoutes.map(
 (route) => <AuthRoute key={route.path} {...route}/>
)}
{adminRoutes.map(
 (route) => <AuthRoute key={route.path} {...route}/>
)}

登入設定許可權

在我們的 AuthRoute 裡面用到了 user: { role } 這個變數,但是我們還沒設定它。真實專案中一般是登入的時候後端API會返回當前使用者的角色,然後前端將這個許可權資訊儲存在一些狀態管理工具裡面,比如 Redux 。我們這裡直接在 Login 頁面寫死兩個按鈕來模擬這個許可權了,使用者的配置就用根元件的 state 來管理了, Login 頁面的兩個按鈕會改變對應的 state

import React from 'react';
import { Link } from 'react-router-dom';

function Login(props) {
 const {loginAsUser,loginAsAdmin,history} = props;

 const userLoginHandler = () => {
 loginAsUser();  // 呼叫父級方法設定使用者許可權
 history.replace('/backend');  // 登入後跳轉後臺頁面
 }

 const adminLoginHandler = () => {
 loginAsAdmin();  // 呼叫父級方法設定管理員許可權
 history.replace('/admin');  // 登入後跳轉管理員頁面
 }

 return (
 <>
  <h1>登入頁</h1>
  <button onClick={userLoginHandler}>普通使用者登入</button>
  <br/><br/>
  <button onClick={adminLoginHandler}>管理員登入</button>
  <br/><br/>
  <Link to="/">回首頁</Link>
 </>
 );
}

export default Login;

到這裡我們這個簡單的路由鑑權就完成了,具體跑起來效果如下:

使用React-Router實現前端路由鑑權的示例程式碼

本文全部程式碼已經上傳GitHub,大家可以拿下來玩玩: https://github.com/dennis-jiang/Front-End-Knowledges/tree/master/Examples/React/react-router-usage

總結

  • React-Router 可以用來管理前端的路由跳轉,是 React 生態裡面很重要的一個庫。
  • React-Router 為了同時支援瀏覽器和 React-Native ,他分拆成了三個包 react-router 核心包, react-router-dom 瀏覽器包, react-router-native 支援 React-Native 。使用時不需要引入 react-router ,只需要引入需要的平臺包就行。
  • 對於需要不同許可權的路由,我們可以將他們拎出來分好類,單獨建成一個檔案,如果路由不多,放在一個檔案匯出多個數組也行。
  • 對於需要鑑權的路由,我們可以用一個高階元件將許可權校驗的邏輯封裝在裡面,其他頁面只需要加好配置,完全不用關心鑑權的問題。

本文內容偏簡單,作為熟悉 React-Router 的用法還不錯,但是我們不能只會用,還要知道他的原理。下篇文章我們就來看看 React-Router 的原始碼裡面蘊藏了什麼奧祕,大家可以點個關注不迷路,哈哈~

參考資料

官方文件:https://reactrouter.com/web/guides/quick-start

GitHub原始碼地址:https://juejin.im/post/5e3ffc85518825494e2772fd

到此這篇關於使用React-Router實現前端路由鑑權的示例程式碼的文章就介紹到這了,更多相關React-Router 前端路由鑑權內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!