← Назад к вопросам

Как определить роль пользователя?

2.0 Middle🔥 111 комментариев
#JavaScript Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Роль пользователя определяется несколькими способами в зависимости от архитектуры приложения: из JWT токена, из API ответа при логине, из контекста приложения или из базы данных.

1. Определение роли из JWT токена

// Декодирование JWT на фронтенде
const decodeToken = (token) => {
  try {
    const base64Url = token.split('.')[1];
    const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
    const jsonPayload = decodeURIComponent(
      atob(base64).split('').map((c) => {
        return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
      }).join('')
    );
    return JSON.parse(jsonPayload);
  } catch (err) {
    console.error('Invalid token', err);
    return null;
  }
};

// Получение роли из токена
const getRole = () => {
  const token = localStorage.getItem('token');
  if (!token) return null;
  
  const payload = decodeToken(token);
  return payload?.role; // или payload?.roles (массив ролей)
};

2. Определение роли из контекста приложения

// AuthContext.js
import { createContext, useState, useCallback } from 'react';

export const AuthContext = createContext();

export function AuthProvider({ children }) {
  const [user, setUser] = useState(null);

  const login = async (email, password) => {
    const response = await fetch('/api/v1/auth/login', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ email, password }),
    });
    
    const data = await response.json();
    setUser(data.user); // { id, email, role: 'admin' }
    localStorage.setItem('token', data.accessToken);
  };

  const getRole = useCallback(() => {
    return user?.role || null;
  }, [user]);

  return (
    <AuthContext.Provider value={{ user, login, getRole }}>
      {children}
    </AuthContext.Provider>
  );
}

// Использование в компоненте
import { useContext } from 'react';

function UserProfile() {
  const { user, getRole } = useContext(AuthContext);
  const role = getRole();

  return (
    <div>
      <p>Пользователь: {user?.email}</p>
      <p>Роль: {role}</p>
    </div>
  );
}

3. Определение роли из API при логине

// При успешном логине сервер отправляет роль
const handleLogin = async (email, password) => {
  const response = await fetch('/api/v1/auth/login', {
    method: 'POST',
    body: JSON.stringify({ email, password }),
  });

  const { user, accessToken } = await response.json();
  
  // Роль уже в объекте user
  const userRole = user.role; // 'admin', 'user', 'moderator'
  
  // Сохраняем полные данные пользователя
  sessionStorage.setItem('user', JSON.stringify(user));
  localStorage.setItem('token', accessToken);
};

4. Проверка доступа к защищённым маршрутам

// ProtectedRoute.jsx
import { Navigate } from 'react-router-dom';
import { useContext } from 'react';
import { AuthContext } from './AuthContext';

export function ProtectedRoute({ children, requiredRole }) {
  const { user, getRole } = useContext(AuthContext);
  const userRole = getRole();

  // Если нет авторизации
  if (!user) {
    return <Navigate to="/login" replace />;
  }

  // Если требуется определённая роль
  if (requiredRole && userRole !== requiredRole) {
    return <Navigate to="/forbidden" replace />;
  }

  return children;
}

// Использование
<BrowserRouter>
  <Routes>
    <Route path="/" element={<Home />} />
    <Route path="/login" element={<Login />} />
    <Route 
      path="/admin" 
      element={
        <ProtectedRoute requiredRole="admin">
          <AdminPanel />
        </ProtectedRoute>
      }
    />
  </Routes>
</BrowserRouter>

5. Проверка роли в компонентах

// Условный рендеринг на основе роли
function Dashboard() {
  const { user } = useContext(AuthContext);
  const isAdmin = user?.role === 'admin';
  const isModerator = user?.role === 'moderator';

  return (
    <div>
      {isAdmin && <AdminPanel />}
      {isModerator && <ModerationQueue />}
      <UserContent />
    </div>
  );
}

6. Проверка роли при API запросах

// Утилита для добавления токена и роли в заголовки
const fetchWithAuth = async (url, options = {}) => {
  const token = localStorage.getItem('token');
  const user = JSON.parse(sessionStorage.getItem('user') || '{}');
  
  return fetch(url, {
    ...options,
    headers: {
      ...options.headers,
      'Authorization': `Bearer ${token}`,
      'X-User-Role': user.role,
    },
  });
};

// Использование
const deleteUser = async (userId) => {
  const response = await fetchWithAuth(`/api/v1/users/${userId}`, {
    method: 'DELETE',
  });
  
  return response.json();
};

7. Role-Based Access Control (RBAC)

// Константы ролей
export const ROLES = {
  ADMIN: 'admin',
  MODERATOR: 'moderator',
  USER: 'user',
  GUEST: 'guest',
};

// Матрица доступа
const PERMISSIONS = {
  [ROLES.ADMIN]: ['read', 'create', 'update', 'delete'],
  [ROLES.MODERATOR]: ['read', 'update'],
  [ROLES.USER]: ['read'],
  [ROLES.GUEST]: [],
};

// Проверка доступа
const hasPermission = (role, action) => {
  return PERMISSIONS[role]?.includes(action) ?? false;
};

// Использование
if (hasPermission(user.role, 'delete')) {
  // Показываем кнопку удаления
}

Выбор метода зависит от требований безопасности и архитектуры приложения. В production рекомендуется проверять роль как на фронтенде (для UX), так и на бэкенде (для безопасности).