В чём разница между 401 и 403?
Разница между 401 Unauthorized и 403 Forbidden — это разница между "кто вы?" и "что вам разрешено?".
Junior Level
Разница между 401 Unauthorized и 403 Forbidden — это разница между “кто вы?” и “что вам разрешено?”.
401 Unauthorized — “Я вас не знаю”
- Сервер не знает пользователя
- Нужно войти в систему (залогиниться)
- Пример: Вы пришли на работу без пропуска
GET /profile
→ 401 Unauthorized
→ Фронтенд перенаправляет на страницу логина
403 Forbidden — “Я вас знаю, но вам нельзя”
- Сервер знает пользователя, но запрещает действие
- Повторный логин не поможет — проблема в правах доступа
- Пример: У вас есть пропуск в офис, но не в серверную
GET /admin
→ 403 Forbidden
→ Фронтенд показывает "Доступ запрещён"
Простая аналогия:
- 401: Охранник спрашивает: “Кто вы?” (нужно предъявить удостоверение)
- 403: Охранник говорит: “Я вас знаю, Иванов, но вам нельзя в этот кабинет”
Middle Level
401 Unauthorized (Identity Unknown)
- Суть: Сервер не знает пользователя
- RFC 9110 Requirement: RFC 9110 требует, чтобы ответ 401 содержал заголовок
WWW-Authenticate(например,WWW-Authenticate: Bearer realm="api"). Однако в production API Gateway может его удалять — это нормально для token-based аутентификации. - Действие: Типичное поведение фронтенда — обновить токен через Refresh Token Flow или перенаправить на страницу логина.
403 Forbidden (Identity Known)
- Суть: Сервер знает пользователя, но запрещает действие
- Действие: Повторный логин не поможет. Это проблема прав доступа (Scopes, Roles, ACL).
- Scopes — разрешения на уровне API (например,
read:users). - Roles — роли пользователя (ADMIN, USER).
- ACL (Access Control List) — таблица соответствия пользователей и ресурсов.
- Scopes — разрешения на уровне API (например,
Реализация в Spring Security 6.x
В Spring Security эти две ошибки обрабатываются разными компонентами:
AuthenticationEntryPoint: Срабатывает, когда анонимный пользователь пытается зайти на защищённый эндпоинт (генерирует 401)AccessDeniedHandler: Срабатывает, когда пользователь залогинен, но егоGrantedAuthorityнедостаточно (генерирует 403)
Пограничные случаи
- Expired Token: Если JWT просрочен — вернуть 401, а не 403. Мобильные приложения используют 401 как триггер для обновления сессии
- IP Blocking / Rate Limiting: 403 может использоваться для блокировки по IP (WAF). Пользователь аутентифицирован, но инфраструктура запрещает доступ
- CSRF: В Spring Security отсутствие или невалидность CSRF-токена приводит к 403 Forbidden, даже если пользователь — супер-админ
Диагностика
- Всплеск 401 может означать проблемы с Identity Provider (Keycloak, Auth0) или Brute-force атаку
- Постоянные 403 от легитимных пользователей — признак бага в интерфейсе или маппинге ролей
Senior Level
Когда НЕ использовать 401/403
- Не возвращайте 401 для публичных ресурсов — это сбивает с толку
- Не используйте 403 для rate limiting — для этого есть 429 Too Many Requests
- Для несуществующих ресурсов лучше 404, чем 403 (чтобы не раскрывать существование)
Security by Obscurity (Скрытие через 404)
Иногда, если пользователь пытается получить доступ к секретному ресурсу (например, /admin/top-secret), сервер может вернуть 404 Not Found вместо 403 Forbidden.
Зачем? Чтобы злоумышленник не знал, существует ли ресурс вообще. Ответ 403 подтверждает существование ресурса (“он тут есть, но я тебе не дам”).
OAuth2 Scopes vs Roles
В современных системах 403 часто возникает из-за нехватки Scopes в JWT токоне:
- У вас есть роль
USER(авторизация пройдена) - Но токен не имеет scope
write(доступ к POST методу запрещён)
Компоненты Spring Security (детали)
AuthenticationEntryPoint
Обрабатывает ситуации, когда неаутентифицированный пользователь пытается получить доступ к защищённому ресурсу. Должен инициировать процесс аутентификации.
AccessDeniedHandler
Обрабатывает ситуации, когда аутентифицированный пользователь не имеет необходимых прав. Может логировать попытки несанкционированного доступа.
Диагностика и Мониторинг
- Metric:
auth_failures_total: Всплеск 401 — проблемы с Identity Provider или Brute-force атака - Monitoring 403s: Постоянные 403 от легитимных пользователей — баг в интерфейсе (кнопки без прав) или в маппинге ролей
- Audit Logging: Все ответы 403 должны логироваться с указанием ID пользователя и требуемого права для отдела безопасности
🎯 Шпаргалка для интервью
Обязательно знать:
- 401 Unauthorized = «не знаю кто вы» — нужна аутентификация, типичное действие — редирект на логин
- 403 Forbidden = «знаю, но нельзя» — проблема в правах доступа (roles, scopes, ACL)
- 401 по RFC 9110 должен содержать заголовок WWW-Authenticate
- В Spring Security: AuthenticationEntryPoint → 401, AccessDeniedHandler → 403
- Expired JWT = 401 (не 403), мобильные приложения используют 401 для обновления сессии
- Security by Obscurity: иногда возвращают 404 вместо 403, чтобы не раскрывать существование ресурса
- Rate limiting = 429, не 403; CSRF-ошибка = 403 даже для супер-админа
Частые уточняющие вопросы:
- Что делать фронтенду при 401? — Обновить токен через Refresh Token или перенаправить на логин
- Что делать фронтенду при 403? — Показать «доступ запрещён», повторный логин не поможет
- Когда лучше вернуть 404 вместо 403? — Для секретных ресурсов, чтобы не подтверждать их существование
- Чем Scopes отличаются от Roles? — Scopes — разрешения на уровне API (read:users), Roles — роли пользователя (ADMIN, USER)
Красные флаги (НЕ говорить):
- «401 и 403 — одно и то же» — 401 = не аутентифицирован, 403 = аутентифицирован, но нет прав
- «Для rate limiting нужен 403» — для этого есть 429 Too Many Requests
- «Повторный логин решит проблему 403» — 403 = проблема в правах, не в аутентификации
- «Expired Token = 403» — просроченный токен = 401, клиент должен обновить сессию
Связанные темы:
- [[Какие HTTP статус коды вы знаете]]
- [[Что означает Stateless в контексте REST]]
- [[Что такое REST]]
- [[Что такое RESTful API дизайн]]
- [[Как правильно именовать REST endpoints]]