大多數的應用都需要身份驗證機制和授權機制,當驗證機制確認某些實體是合法使用者時,授權機制將根據使用者的角色和許可權去決定使用者是否被允許去執行這些操作
在大多數情況下,我們通常不需要特殊的模組或者庫來處理授權,大多數的工具函式已經足夠了。由你提供的應用內的驗證或者授權解決方法是可以變化的。你可能會決定把使用者的狀態放到Redux去管理,你也可能建立一個專用的模組,等等...
讓我們看看如何在React中處理一個簡單的基於角色的授權機制
簡單的授權機制
假設我們有一個使用者物件,這個物件通常是在完成登入後通過呼叫一個終端獲得的,它有以下的結構
const user = {
name: 'Jackator',
// ...
roles: ['user'],
rights: ['can_view_articles']
};
複製程式碼
使用者有幾個可以分組為角色的許可權。對於你的應用,你可能只需要角色,或者只需要許可權或者兩者都需要,那都不是問題。REST API 可能給你巢狀在角色裡的許可權,那也不是問題,請記住一點,你要根據你的需求來調整解決方案。最重要的是我們擁有一個使用者物件。
之後我們建立一個auth.js檔案,裡面有一些工具方法可能幫助我們去檢查使用者的授權情況
auth.js
export const isAuthenticated = user => !!user;
export const isAllowed = (user, rights) =>
rights.some(right => user.rights.includes(right));
export const hasRole = (user, roles) =>
roles.some(role => user.roles.includes(role));
複製程式碼
通過使用Array prototype上的some和includes方法,我們檢查了客戶是否用友至少一個許可權或者角色,這應該足以執行一些基本的許可權檢查
因為使用者物件可以儲存在任何地方,以Redux為例子,我們允許將它作為引數傳遞給函式。
我們最終建立了一個簡單的React元件,它使用了auth.js裡的函式為了能夠根據條件去顯示介面上不同的部分
App.js
import React from 'react';
import { render } from "react-dom";
import { hasRole, isAllowed } from './auth';
const user = {
roles: ['user'],
rights: ['can_view_articles']
};
const admin = {
roles: ['user', 'admin'],
rights: ['can_view_articles', 'can_view_users']
};
const App = ({ user }) => (
<div>
{hasRole(user, ['user']) && <p>Is User</p>}
{hasRole(user, ['admin']) && <p>Is Admin</p>}
{isAllowed(user, ['can_view_articles']) && <p>Can view Articles</p>}
{isAllowed(user, ['can_view_users']) && <p>Can view Users</p>}
</div>
);
render(
<App user={user} />,
document.getElementById('root')
);
複製程式碼
我們使用 && 邏輯符進行短路評估(譯者注:這裡我直譯了,大概的意思使用&&來決定頁面內容是否展示)。在這裡,如果hasRole或者isAllowed函式返回true,&&符號後面的內容建會被渲染。
嘗試去將user改變為admin,你將看到admin相關的介面會被顯示
條件路由
如果你使用了React Router,你可以使用相同的方法,根據條件去渲染路由:
import React from 'react';
import { BrowserRouter, Switch, Route } from 'react-router-dom';
const App = ({ user }) => (
<BrowserRouter>
<Switch>
{hasRole(user, ['user']) && <Route path='/user' component={User} />}
{hasRole(user, ['admin']) && <Route path='/admin' component={Admin} />}
<Route exact path='/' component={Home} />
</Switch>
</BrowserRouter>
);
複製程式碼
React Router 讓Route元件的宣告和路由組合變得很容易,我們可以利用它:如果*元件通過hasRole的校驗被渲染,Route將會被Router*增加和執行