Используйте React-Router для реализации внешней аутентификации маршрутизации.

внешний интерфейс React.js

React-RouterЭто очень важная часть экосистемы React. Теперь маршрутизация одностраничных приложений React в основном управляется самим внешним интерфейсом, в отличие от внутренней маршрутизации в прошлом. Обычно используемая библиотека для маршрутизации управления React:React-Router. Я хочу написать эту статьюReact-RouterИспользование , но введение API слишком мягкое,И официальная документация написана очень хорошо, я буду использовать общий сценарий разработки, чтобы увидетьReact-RouterКак это используется. Наша общая система будет иметь ограничения на права доступа пользователей, и некоторые страницы могут требовать, чтобы пользователи имели определенные права доступа. В этой статье используетсяReact-RouterДля реализации модели внешней аутентификации.

Весь код в этой статье был загружен на GitHub, вы можете снять его и поиграть:GitHub.com/Денис — см....

Пример приложения

Функция, которая будет реализована в этой статье, представляет собой сценарий, с которым часто сталкиваются все, то есть управление разными ролями пользователей для доступа к разным страницам.Всего здесь четыре страницы:

  1. /index: домашняя страница сайта
  2. /login: страница авторизации
  3. /backend: Фоновая страница
  4. /admin: Страница управления

Есть также три другие роли:

  1. 未登录用户: Доступ возможен только к домашней странице веб-сайта./indexи страница входа/login
  2. 普通用户: Вы можете посетить домашнюю страницу веб-сайта/index, страница авторизации/loginи бэкэнд-страница/backend
  3. 管理员: Может получить доступ к странице администратора/adminи все остальные страницы

Представляем React-маршрутизатор

Чтобы реализовать маршрутную аутентификацию, нам нужно идти шаг за шагом.Сначала мы используем React-Router для создания простого проекта с этими страницами. мы напрямую используемcreate-react-appСоздал новый проект, затем построилpagesПапка, содержащая упомянутые ранее страницы:

image-20200710152739352

Давайте сначала напишем простую страницу, давайте сначала напишем заголовок, например:

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;

Пока что наше приложение работает так:

Jul-10-2020 17-35-36

Модульное деление

Хотя наш прыжок реализован, каждый может получить доступ к любой странице.Наше предыдущее требование - ограничить доступ к страницам в соответствии с ролью входа.Прежде чем писать код, давайте подумаем, как это сделать. Конечно, самый интуитивно понятный и простой способ — определить роль текущего пользователя на каждой странице и сообщить об ошибке или вернуться на домашнюю страницу, если она не совпадает. У нас сейчас всего несколько страниц, и это вроде бы нормально, но если наше приложение станет больше и страниц будет больше, то проверять каждую страницу по одному разу будет очень многократно, поэтому стоит подумать об этой проблеме под другим углом.

Присмотревшись повнимательнее, мы на самом деле имеем три роли, соответствующие трем разным разрешениям. Эти три разрешения также связаны иерархически. Разрешения высокого уровня включают в себя разрешения более низкого уровня, поэтому наши страницы также можно разделить на эти разрешения.

  1. 公共页面: может быть доступен всем, даже без входа в систему, включая домашнюю страницу и страницу входа на веб-сайт.
  2. 普通页面: страницы, к которым могут получить доступ обычные пользователи, вошедшие в систему.
  3. 管理员页面: страница, доступ к которой имеют только администраторы

Чтобы управлять этими тремя видами страниц, мы можем извлечь их в три файла и поместить в отдельную папку.routesВнутри три файла называютсяpublicRoutes.js,privateRoutes.js,adminRoutes.js:

image-20200721170127221

Для каждого файла маршрута мы можем организовать такие маршруты в массив, затемexportВыйдите, чтобы позвонить снаружи, напримерpublicRoutes.js:

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

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

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.js,adminRoutes.jsМаршрутизация внутри будет лучше, чемpublicRoutes.jsеще два параметра:

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

const privateRoutes = [
  {
    path: '/backend',
    component: Backend,
    exact: true,
    role: 'user',       // 当前路由需要的角色权限
    backUrl: '/login'   // 不满足权限跳转的路由
  },
];

export default privateRoutes;

adminRoutes.jsпохоже на запись:

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

const adminRoutes = [
  {
    path: '/admin',
    component: Admin,
    exact: true,
    role: 'admin',       // 需要的权限是admin
    backUrl: '/backend'  // 不满足权限跳回后台页面
  },
];

export default adminRoutes;

Затем мы можем написать наш высокоуровневый компонент, который мы назовем какAuthRouteОбратите внимание, что backend 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оказаниеadminRoutesа такжеprivateRoutes:

// ... 省略其他代码 ...

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

Войдите, чтобы установить разрешения

в нашемAuthRouteиспользуется вuser: { role }эту переменную, но мы еще не установили ее. В реальных проектах при входе back-end API будет возвращать роль текущего пользователя, а затем front-end будет сохранять эту информацию о разрешениях в некоторых инструментах управления состоянием, таких как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;

На этом наша простая аутентификация маршрутизации завершена.Конкретный эффект выполнения выглядит следующим образом:

Jul-23-2020 20-40-37

Весь код в этой статье был загружен на GitHub, вы можете снять его и поиграть:GitHub.com/Денис — см....

Суммировать

  1. React-RouterЕго можно использовать для управления скачком маршрутизации внешнего интерфейса, даReactОчень важная библиотека в экологии.
  2. React-RouterДля поддержки как браузера, так иReact-Native, он разделился на три пакетаreact-routerосновной пакет,react-router-domпакет браузера,react-router-nativeслужба поддержкиReact-Native. Нет необходимости импортировать при использованииreact-router, просто импортируйте необходимый пакет платформы.
  3. Для маршрутов, требующих разных прав, мы можем их вынести и классифицировать в отдельный файл, а если маршрутов немного, то также можно экспортировать несколько массивов в один файл.
  4. Для маршрутов, требующих аутентификации, мы можем использовать расширенный компонент, чтобы инкапсулировать в нем логику проверки разрешений, а остальные страницы нужно только настроить, и нам вообще не нужно заботиться об аутентификации.

Содержание этой статьи относительно простое, какReact-RouterИспользование неплохое, но мы можем не просто использовать его, но и знать его принцип. Следующая статья давайте посмотримReact-RouterКакие загадки в исходном коде ?

использованная литература

Официальная документация:react-router.com/Web/guides/…

Адрес источника GitHub:GitHub.com/реагировать поезд я…

В конце статьи спасибо, что потратили свое драгоценное время на чтение этой статьи. Если эта статья немного поможет вам или вдохновит, пожалуйста, не скупитесь на лайки и звезды GitHub. Ваша поддержка является движущей силой для автор продолжать творить.

Добро пожаловать, чтобы обратить внимание на мой общедоступный номербольшой фронт атакиПолучите высококачественные оригиналы впервые~

Цикл статей "Передовые передовые знания":nuggets.capable/post/684490…

Адрес GitHub с исходным кодом из серии статей «Advanced Front-end Knowledge»:GitHub.com/Денис — см....