Авторизация и роли

Naive UI предоставляет гибкие инструменты для создания пользовательских интерфейсов, однако вопросы управления доступом и ролями пользователей требуют интеграции с механизмами авторизации. В JavaScript-приложениях на базе Naive UI авторизация чаще всего строится вокруг реактивного состояния, маршрутизации и управления компонентами в зависимости от прав пользователя.


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

Для отслеживания текущего пользователя и его ролей применяется реактивное состояние, например через Vue 3 Composition API:

import { reactive, computed } from 'vue';

export const userState = reactive({
  isAuthenticated: false,
  roles: []
});

export const hasRole = (role) => computed(() => userState.roles.includes(role));
  • isAuthenticated отражает факт входа пользователя.
  • roles содержит массив ролей, например ['admin', 'editor'].
  • hasRole возвращает реактивное булево значение, которое можно использовать для условного отображения компонентов.

Защита маршрутов

Naive UI не предоставляет встроенной системы маршрутизации, но в связке с Vue Router можно организовать доступ к страницам:

import { createRouter, createWebHistory } from 'vue-router';
import { userState } from './userState';
import Home from './pages/Home.vue';
import Admin from './pages/Admin.vue';
import Login from './pages/Login.vue';

const routes = [
  { path: '/', component: Home },
  { path: '/admin', component: Admin, meta: { roles: ['admin'] } },
  { path: '/login', component: Login }
];

const router = createRouter({
  history: createWebHistory(),
  routes
});

router.beforeEach((to, from, next) => {
  const requiredRoles = to.meta.roles;
  if (requiredRoles) {
    if (!userState.isAuthenticated) {
      next('/login');
    } else if (!requiredRoles.some(role => userState.roles.includes(role))) {
      next('/');
    } else {
      next();
    }
  } else {
    next();
  }
});

export default router;

Ключевые моменты:

  • meta.roles задаёт роли, которые могут получить доступ к маршруту.
  • Навигационный охранник beforeEach проверяет аутентификацию и роль пользователя.
  • Пользователь без прав перенаправляется на главную или страницу входа.

Условное отображение компонентов

В Naive UI компоненты можно скрывать или изменять их состояние на основе роли пользователя. Например, кнопка, доступная только администраторам:

<template>
  <n-button v-if="isAdmin" @click="deleteItem">Удалить</n-button>
</template>

<script setup>
import { hasRole } from './userState';

const isAdmin = hasRole('admin');

function deleteItem() {
  console.log('Элемент удален');
}
</script>

Выделенные моменты:

  • v-if позволяет полностью исключить компонент из DOM, если пользователь не обладает нужной ролью.
  • Использование реактивных вычислений (computed) обеспечивает мгновенное обновление интерфейса при изменении ролей.

Интеграция с API авторизации

Для проверки токенов и получения данных о ролях обычно используется асинхронный запрос к серверу:

import axios from 'axios';
import { userState } from './userState';

export async function login(username, password) {
  try {
    const response = await axios.post('/api/login', { username, password });
    userState.isAuthenticated = true;
    userState.roles = response.data.roles;
  } catch (error) {
    console.error('Ошибка входа:', error);
    userState.isAuthenticated = false;
    userState.roles = [];
  }
}

Ключевые моменты:

  • Полученные с сервера роли хранятся в реактивном состоянии.
  • Любые компоненты, использующие hasRole, автоматически реагируют на обновление ролей.
  • При ошибке аутентификации состояние пользователя сбрасывается.

Роль “гостя” и динамическое меню

Часто необходимо отображать меню, зависящее от ролей пользователя:

<template>
  <n-menu :options="menuOptions" />
</template>

<script setup>
import { computed } from 'vue';
import { userState } from './userState';

const menuOptions = computed(() => {
  const options = [{ label: 'Главная', key: '/' }];

  if (userState.roles.includes('admin')) {
    options.push({ label: 'Админка', key: '/admin' });
  }
  if (userState.roles.includes('editor')) {
    options.push({ label: 'Редактор', key: '/editor' });
  }

  return options;
});
</script>
  • Меню формируется динамически на основе массива ролей.
  • Любое изменение ролей пользователя мгновенно отражается на интерфейсе.

Рекомендации по безопасности

  • Не полагаться только на фронтенд: Все проверки ролей должны дублироваться на сервере.
  • Минимизировать видимость компонентов: Использовать v-if, а не только disabled.
  • Обновление токена: При изменении ролей важно синхронизировать состояние с сервером, чтобы не допустить несоответствия между интерфейсом и правами пользователя.

Этот подход обеспечивает интеграцию Naive UI с современными системами авторизации и ролевого управления, делая интерфейсы динамичными, безопасными и управляемыми.