JavaRush /Курсы /Spring Security /Default user, generated password и вход

Default user, generated password и вход

Spring Security
2 уровень , 2 лекция
Открыта

1. Default user в Spring Boot

После подключения Spring Security разработчику нужен не только «замок на двери», но и способ самому проверить, что он открывается. Иначе вы первым делом запираете себя. Точно такая же дилемма возникает в приложении: защита уже закрыла доступ, а вам нужно убедиться, что она работает и что в защищённую зону действительно можно попасть «как положено».

Поэтому Spring Boot делает прагматичную вещь: если вы подключили spring-boot-starter-security и ещё не настроили собственных пользователей, платформа создаёт временного пользователя «для первого запуска». По сути, это технический гостевой пропуск для разработчика: с ним можно руками проверить «да, endpoint’ы закрылись», «да, можно войти», «да, после входа запросы проходят».

В документации Spring Security это показано на уровне упрощённой логики автоконфигурации: создаётся пользователь с логином user и случайным паролем, который выводится в консоль при старте приложения.

Важно поймать правильную мысль: default user не существует для того, чтобы ваш продукт «работал в проде без настроек». Он существует, чтобы вы не застряли у закрытой двери в момент, когда security уже включилась, а прикладная модель пользователей ещё не готова.

2. Default user и пользователь проекта

Когда человек впервые видит в логах “Using generated security password…”, очень легко подумать: «О, это и есть мой пользователь. Значит, у меня уже есть аккаунты, роли, права…». И вот здесь нужно аккуратно притормозить, сделать глоток воды и честно сказать: нет, это не пользователь вашей контент-платформы. Это служебный пользователь Spring Boot.

Если вспомнить термины из первого дня, то default user — это просто самый минимальный principal, который позволяет пройти authentication и попасть в приложение. У него есть credentials (логин/пароль), но он не отражает вашу бизнес-карту доступа. Для него не существует ни «owner-only», ни «editor-only», ни «admin-only»; он не знает, что такое «мой черновик» и «чужой черновик», и не понимает, что часть API вообще должна быть публичной.

У такого пользователя есть ещё одна характерная особенность: он обычно один. В упрощённом примере автоконфигурации создаётся user с ролью USER. Для сценария «проверить, что дверь вообще закрывается и открывается» этого достаточно, но для тестирования матрицы доступа проекта, где будут разные роли и разные зоны, — уже нет.

Чтобы не путаться, удобно держать в голове такую сравнительную таблицу:

Характеристика default user (сейчас) Пользователь вашего проекта (позже)
Цель Быстро показать, что security работает Реальный доступ к данным и операциям продукта
Где хранится В памяти приложения, автоматически В вашей модели (сначала in-memory осознанно, затем БД)
Пароль Случайный, печатается при старте Управляемый вами (и хранится безопасно)
Роли и права Минимально и «для галочки» Отражают бизнес-сценарии (USER/EDITOR/ADMIN, permissions)
Время жизни Для первого запуска / локальной проверки Для реального использования приложения

В этой лекции наша задача не «построить user management». Наша задача — не бояться default user и уметь использовать его как диагностический инструмент.

3. Generated password и первый вход

Generated password в логах

Переходим к самому практичному вопросу дня: «Окей, пользователь есть. Где взять пароль?» Ответ сначала раздражает, а потом становится привычным: в логах старта приложения.

Когда вы запускаете Spring Boot-приложение с подключённым starter’ом, в консоли появляется строка примерно такого вида:

# Фрагмент лога при старте Spring Boot приложения
Using generated security password: 8e557245-73e2-4286-969a-ff57fe326336

Такая строка приводится и в официальном getting started для servlet-приложений: при запуске через Gradle/Maven/Jar Spring Boot печатает “generated security password” в вывод.

Почему именно лог, а не, например, файл? Потому что это максимально одноразовый и безопасный для старта способ: пароль не лежит в репозитории, не хранится в открытом виде в конфиге — если вы сами так не сделали, — и при этом его можно быстро скопировать.

Теперь важный нюанс, на котором спотыкаются почти все: пароль генерируется на старте. Это значит, что при каждом перезапуске приложения, особенно если у вас включён devtools и он перезапускает контекст, пароль может измениться. И если вы пытаетесь залогиниться «паролем из вчерашнего запуска», приложение не вредничает — оно просто живёт в настоящем.

Практический совет, который спасает нервы: как только запускаете приложение, сразу найдите строку с паролем и временно сохраните её в заметки. Потеряли — просто перезапустите приложение и возьмите новый пароль. Это быстрее, чем полчаса убеждать себя, что «Spring Security сломался».

Есть и ещё один нюанс: строка находится в логах. Значит, если вы случайно настроили логирование так, что INFO-сообщения не показываются, пароль можно не увидеть, хотя он при этом существует. В таком случае либо поднимаете уровень логов, либо — что для учебного проекта обычно проще — задаёте пароль явно через конфигурацию. Об этом мы поговорим чуть позже.

Первый вход в приложение

Когда вы впервые «входите» в Spring Security-приложение, не нужно пытаться сразу понять всю механику. Сейчас цель скромнее и полезнее: научиться наблюдать. Нам важно увидеть, как защищённое приложение выглядит глазами клиента, и убедиться, что credentials действительно дают доступ туда, куда без них нельзя.

Самый наглядный клиент для первого запуска — браузер. Это не лучший инструмент для тестирования REST API, зато он отлично показывает идею «есть защищённая зона → тебя просят залогиниться». В официальном getting started прямо сказано: если открыть защищённый URL в браузере, приложение редиректит на стандартную login page.

Зафиксируем простой наблюдаемый сценарий на нашем учебном проекте. Добавим endpoint /api/me, который символизирует личную зону пользователя.

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController // Этот контроллер будет доступен через HTTP
public class MeController {

    @GetMapping("/api/me") // Защищённый эндпоинт: без аутентификации сюда не пустит Spring Security
    public String me() {
        // Здесь нет бизнес-логики: нам важно увидеть, что запрос дошёл до контроллера
        return "authenticated zone";
    }
}

Сценарий дальше простой.

Сначала вы открываете в браузере http://localhost:8080/api/me. Если security подключён, вы не увидите “authenticated zone” сразу. Вместо этого попадёте на login page. Это и есть тот самый входной контроль, который появился после подключения starter’а.

Потом вы вводите логин user и тот самый generated password, который нашли в логах. После успешного входа вы снова делаете запрос к /api/me — иногда браузер делает это автоматически, — и уже получаете ответ контроллера.

На этом шаге важно понять одну мысль: контроллер не менялся, код бизнес-логики не менялся, DTO не менялись. Изменилось только одно: между клиентом и контроллером появился обязательный этап «докажи, кто ты». Это и есть начало реального security-слоя.

Ещё одна деталь, которую полезно заметить: после успешного логина Spring Security обычно возвращает вас к тому ресурсу, который вы пытались открыть до логина. На уровне механики это часть стандартного form-login поведения: внутри фреймворка есть обработчик успешного логина, который делает redirect к сохранённому запросу. Мы пока не разбираем, как именно это запоминается; нам важно увидеть, что UX «логин → вернули туда, куда шёл» действительно существует.

Чтобы закрепить картину, можно представить flow так:

sequenceDiagram
    %% Наблюдаемый сценарий: первый заход в защищённый эндпоинт через браузер
    participant B as Браузер
    participant A as Приложение
    B->>A: "GET /api/me"
    A-->>B: "Redirect на login page"
    B->>A: "POST login (user + generated password)"
    A-->>B: "Login successful"
    B->>A: "GET /api/me (повтор)"
    A-->>B: "200 OK + 'authenticated zone'"

Это не «реализация», а просто карта наблюдений: что вы видите глазами клиента на первом запуске.

4. Проверка доступа и удобство разработки

Что доказывает вход default user

После первого успешного входа очень хочется выдохнуть и сказать: «Ну всё, безопасность сделана». Это тот самый момент, когда хочется ласково, но настойчиво напомнить: нет, вы просто включили свет в комнате. Мебель ещё не расставлена.

Что именно доказывает успешный вход под default user?

Он показывает, что приложение теперь умеет требовать authentication и умеет пропускать запросы дальше, если credentials верные. Это уже важный результат, потому что мы видим: security действительно влияет на доступность endpoint’ов.

Но он не доказывает, что у вас правильная матрица доступа. Почему? Потому что сейчас Spring Security по умолчанию защищает «всё подряд». В официальном getting started это прямо сформулировано как ожидание runtime: для любого endpoint требуется аутентифицированный пользователь, и одновременно регистрируется default user с паролем, который печатается в консоль.

И вот здесь появляется полезный учебный контраст: у нас в проекте есть зона, которая по бизнес-смыслу public, например /api/public/**. Но по умолчанию она тоже закрыта. Это не ошибка — это стартовая позиция. Мы ещё не научили приложение отличать public от private. Пока что мы только научили его «не пускать кого попало».

Если хотите сделать быструю проверку без браузера, можно использовать curl с basic credentials. В getting started есть такой пример: без credentials вы получите 401, а с -u user:<password> запрос пройдёт и вы получите уже «честный» ответ приложения — например, 404, если URL вообще не существует.

# -i: показать заголовки ответа (статус, WWW-Authenticate и т.д.)
# -u: передать basic credentials (username:password)
curl -i -u user:ВАШ_СГЕНЕРИРОВАННЫЙ_ПАРОЛЬ http://localhost:8080/api/me

Я сознательно не углубляюсь в то, почему браузер показывает одно, а curl — другое: это тема следующей лекции дня. Здесь нам важно лишь понять, что credentials работают не «магически в браузере», а как общий способ пройти проверку личности.

Фиксируем логин и пароль для разработки

С generated password есть бытовая проблема: он случайный, его нужно каждый раз искать в логах, а иногда приложение перезапускается чаще, чем вы успеваете моргнуть. В какой-то момент начинает казаться, что вы не изучаете Spring Security, а проходите квест «найди UUID в консоли».

Spring Boot позволяет задать логин и пароль для default user через конфигурацию. В документации Spring Boot про security говорится прямо: можно изменить username и password, задав spring.security.user.name и spring.security.user.password.

Для учебного проекта это удобно сделать в application.yml локально:

spring:
  security:
    user:
      # Фиксируем username для локальной разработки
      name: user
      # Фиксируем пароль, чтобы не искать UUID в логах после каждого перезапуска
      password: dev-password

Смысл здесь не в том, чтобы «сделать пароль простым навсегда». Смысл в том, чтобы перестать тратить время на поиск значения в логах и сосредоточиться на наблюдениях: какие endpoint’ы закрыты, как выглядит login page и что меняется после успешной аутентификации.

Но есть важная дисциплина, которую хочется заложить сразу — без страшилок, но честно. Такой пароль нельзя воспринимать как норму для продакшена. Во-первых, его легко забыть как «учебный» и утащить в репозиторий. Во-вторых, в голове закрепится опасная модель: «безопасность = пароль в конфиге», а мы позже будем строить нормальную модель пользователей.

Поэтому хороший компромисс для учебного проекта звучит так: задаём фиксированный пароль локально, чтобы не отвлекаться, но держим в голове, что это временная заглушка.

На этом месте полезно отделить две вещи. default user отвечает только на вопрос «можно ли вообще пройти вход». А вот как выглядит отказ без входа — уже отдельная история: браузер чаще увидит login page, а API-клиент — 401. Это один и тот же baseline, просто два разных способа встретить неаутентифицированный запрос.

5. Типичные ошибки при первом входе

Ошибка №1: пытаться логиниться не тем username.
Очень частая ситуация: студент видит “generated password”, но не замечает, что username по умолчанию — user. В итоге вводится “admin”, “myname”, “root” (потому что душа просит власти), а пароль при этом берётся правильный. Результат — «не входит», и кажется, что security сломался. На самом деле сломалась только догадка.

Ошибка №2: перезапустили приложение — а пароль в заметках остался старый.
Это классика. Пароль сгенерирован на старте, вы его скопировали, потом Gradle пересобрал проект, IDE сделала restart, и вы снова пытаетесь зайти со старым значением. Выглядит как «внезапно перестало работать», хотя на деле просто изменились credentials. Если используете generated password, относитесь к нему как к «паролю текущего запуска».

Ошибка №3: искать password в коде контроллера или в application.yml, когда он генерируется.
Сгенерированный пароль выводится в лог старта приложения. Он не живёт в контроллерах, DTO или сервисах, потому что не является частью вашей бизнес-логики. В getting started это показано буквально как строка в консольном выводе “Using generated security password …”. Если вы ищете его в коде, то просто копаете не там.

Ошибка №4: считать, что первый успешный логин означает «доступы настроены».
Успешный логин означает только то, что authentication существует и работает. Он не означает, что /api/public/** действительно публичный, что /api/admin/** действительно админский и что логика «свой/чужой» уже учтена. Сейчас текущий baseline платформы по умолчанию закрывает всё и даёт один технический пропуск внутрь. Это стартовая точка, а не готовая модель безопасности.

Ошибка №5: поставить фиксированный пароль и забыть, что это временный хак.
Задать spring.security.user.password — нормально для локальной разработки, и это поддержанный сценарий. Но опасно превращать это в привычку «пароль хранится в конфиге проекта». На уровне курса мы ещё вернёмся к нормальным подходам, но уже сейчас полезно разделять: «удобно для обучения» и «нормально для жизни».

1
Задача
Spring Security, 2 уровень, 2 лекция
Недоступна
Вход с generated password
Вход с generated password
1
Задача
Spring Security, 2 уровень, 2 лекция
Недоступна
Фиксированные стартовые credentials в application.yml
Фиксированные стартовые credentials в application.yml
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ