0: Всем привет, это Артём Михайлов и онлайн школа коуд китчен. В сегодняшней лекции. Мы реализуем процесс Логина, а также процесс регистрации и, конечно же, познакомимся с такими понятиями, как аутентификация и авторизация. Ну что, погнали? 1
1: Процесс, который мы должны реализовать в данной лекции, это регистрация с точки зрения теории. Про процесс регистрации рассказывать особенно нечего, поэтому давайте сразу же перейдём к практике для того, чтобы у нас вообще была возможность зарегистрировать новых пользователей.
2: Логично, что для этого у нас должна быть энтити юзер, которая и будет хранить всю информацию обо всех пользователях нашего веб приложения. Поэтому 1, что нам нужно сделать, это создать этот entity класс, user и разметить его всеми необходимыми аннотациями, потому что
3: Все данные обо всех пользователях конечно же будут храниться в нашей бд. Итак кликаем на нашу папку entity и создаём там новый класс, называться он будет user давайте немножко приблизим содержимое класса теперь.
4: Нам необходимо определиться с набором полей, которые будут храниться внутри данной сущности, конечно же, это у нас должен быть идентификатор пользователя, поэтому добавляем поле id с типом int. Помимо id, мы также будем хранить информацию об имени нашего
5: Пользователя, поэтому добавляем поле string name. Помимо имени мы также будем хранить информацию об имейле нашего пользователя. Это и будет логин. Поэтому добавляем соответствующее поле и, конечно же, нам необходимо поле, в котором мы будем хранить пароль нашего пользователя. Это будет
6: Тот самый эталонный пароль, который нам пользователь предоставит при регистрации. И мы на своей стороне будем его хранить, чтобы каждый раз, когда пользователь будет логиниться в систему, мы могли сравнивать предоставленный пароль при логине с этим эталонным паролем внутри нашей бд. И чтобы мы
7: Исходя из этого, могли сделать вывод. На той стороне сидит настоящий пользователь или нет. То есть он предоставил реальный свой пароль или какой-то левый. И последнее техническое поле, которое нам необходимо для того, чтобы спринг секьюрити могло правильно работать. Это, конечно же, роль данного пользователя, чтобы
8: Наше приложение могло понимать, кем именно данный пользователь является для нашего приложения. То есть это обычный пользователь или, к примеру, администратор. Поэтому добавим, здесь новое поле. Тип данных. Здесь будет юзер ролл. Это тот самый еннам, который мы создавали в 1 из предыдущих лекций.
9: И само поле. Давайте назовём роул на этом, в принципе, все. Вы, когда создаёте свои веб приложения, вы, конечно же, можете данный класс, user расширять неограниченным количеством дополнительных полей. Если вам нужна какая-то дополнительная информация, например, дата рождения пользователя.
10: Номер телефона может быть, к примеру, помимо имени ещё и фамилия, и отчество и так далее. Вы можете запросить у пользователя при регистрации абсолютно любую информацию, причём часть этих полей они могут быть обязательные, а часть могут быть необязательные, например, все обязательные.
11: Поля пользователь обязательно должен предоставить при регистрации, а уже какую-то дополнительную информацию о себе пользователь может предоставить уже после регистрации где-то на страничке личного кабинета, например, свою дату рождения, или отчество, или свой пол, потому что эти данные, они не
12: Кажутся обязательными и запрашивать их на странице регистрации кажется немного странным. Процесс регистрации, он должен быть всегда максимально простым и не сложным для пользователя. То есть чтобы ему было не лень заполнять миллиард каких-то ненужных полей. Конкретно у нас все будет максимально
13: Чётко и просто мы будем запрашивать имя пользователя, чтобы знать, как к нему обращаться. А также его имейл и пароль. Это необходимо для того, чтобы войти в систему, то есть залогиниться. Ну и, конечно же, роль ролью сам пользователь оперировать нигде, никак не сможет заполнять значения эти, он не сможет, это все.
14: Будет делать наша система под капотом. Весь процесс по работе с ролями он будет скрыт от глаз пользователя. Все это будет реализовано именно нами внутри, в глубине нашего web приложения. Теперь нам необходимо наш класс, так как он является именно энтити классом, разметить всеми нужным.
15: Аннотациями, поэтому погнали. В 1 очередь мы указываем аннотацию энтити, потому что это именно энтити класс. Далее аннотация тейбл. Здесь нам нужно указать название таблицы в бд, с которой мы свяжем данный энтити класс. Напоминаю,
16: Что все таблицы в бд принято называть во множественном числе и маленькими буквами, поэтому все наши пользователи, вся их информация будет храниться в таблице под названием users. Далее каждое поле нам необходимо пометить аннотацией колун для того, чтобы хибернейт смог
17: Связать каждое поле в этом энтити классе с колонкой внутри таблицы бд. Здесь в качестве параметра нам необходимо передать нейм для того, чтобы обозначить название непосредственно колонки внутри таблицы. Для id это, конечно же, просто id для name
18: Это также будет name. Ну и вообще из за того, что у нас все поля, они достаточно простые, состоят из 1 слова у нас названия колонок и полей будут совпадать. Напомню, что различия появляются в тот момент, когда у нас название поля состоит из 2 слов и написано кэмел кейсом. Если
19: Поля в классе мы называем именно кэмел кейсом, то название колонок внутри таблиц. Они должны быть написаны всегда маленькими буквами, и слова мы разделяем именно андерскором, то есть нижним подчёркиванием. У этой аннотации мы в качестве name указываем имейл. Пароль у нас
20: Будет, конечно же, также эсвар, и для Роли мы здесь указываем ролл. Теперь нам необходимо задать констрейнты, то есть ограничения для значений внутри каждого из этих полей, а точнее, колонок в таблице. Во первых, абсолютно
21: Все наши поля, они должны быть not null, то есть обязательные, для что мы и указываем налоб фолс. Давайте скопируем это и продублируем в каждой колонке, потому что пользователь без Роли не может существовать точно так же, как и пользователь.
22: Заполнения.
23: Все наши поля, они должны быть not null, то есть обязательные для заполнения, что мы и указываем налоб фолс. Давайте скопируем это и продублируем в каждой колонке, потому что пользователь без Роли не может существовать точно так же, как и пользователь.
24: Без имени, без имейла и без пароля. Мы не сможем правильно взаимодействовать с таким пользователем, потому что на всех этих данных будет завязано наше веб приложение. Все инамы, такие как user ролл, они у нас хибернейта, конвертируются в тип данных числовой, поэтому здесь
25: Никакие ограничения дополнительные нам указывать не нужно. А вот для 3 строковых полей я предлагаю задать ограничения по количеству символов. Например, для имени. Давайте зададим ограничение, равное 20. Я думаю, 20 символов более чем достаточно, чтобы задать своё имя.
26: Для имейла и пароля мы можем задать ограничение чуть подлинней. Например, это у нас будет длина, равная 30. Если хотите, можете сделать ещё больше. Вообще. Напомню, что правилом хорошего тона считается для всех строковых полей. Указывать ограничения, если мы этого не
27: Сделаем по умолчанию. Длина будет ограничена 200 пятидесятью пятью символами, то есть для абсолютно каждой записи в бд. Для поля с таким ограничением в 255 символов будет выделяться соответствующая память, даже если, к примеру, пользователь предоставит своё
28: Реальное имя, которое состоит из 5 символов по факту в бд, будет выделена память для колонки с именем именно на 255 символов если собрать примерную статистику, то получится, что в среднем количество символов для имени пользователя это, к примеру, 10.
29: При этом по умолчанию выделяется 255. Это более чем в 25 раз больше, чем реальная средняя длина имени, которую будут предоставлять наши пользователи. А это значит, что при огромном количестве пользователей, например, десятки миллионов или сотни это будет значить, что
30: Мы нерационально будем использовать память внутри нашей бд, поэтому всегда старайтесь строковые типы ограничивать какой-то длинной, которая близка к правде. Я считаю, что даже 20 символов или 30 символов это достаточно много, но тем не менее, это уже гораздо эконом.
31: Если бы мы использовали 255 символов по умолчанию. Далее ещё 1 любопытный момент, который мы никогда не указывали, когда работали с хибернейта и с разметкой сущностей различными аннотациями. Я предлагаю данное поле имейл пометить также с помощью
32: Параметры юник тру смотрите всегда для всех полей стоит unique фолс по умолчанию это значит, что разные записи внутри 1 и той же таблицы users могут иметь одинаковое значение для имейла. Когда мы говорим про другие поля, например имя то логично, что данное поле оно
33: Не должно быть уникальным, потому что действительно могут быть пользователи с одинаковым именем или поле пароль. Оно тоже не должно быть уникальным. Логично, что разным людям может прийти в голову один и тот же пароль, который они и установят в свой аккаунт. Но вот такие понятия, как имейл или номер телефона, они
34: Конечно же, по определению уникальны у разных пользователей не может быть один и тот же имейл. Как минимум, когда пользователь будет на странице Логина вводить свой имейл, мы должны по этому имейлу однозначно найти, то есть идентифицировать пользователя где-то внутри нашей бд. Поэтому логи
35: Логично, что к 1 иммейлу может быть привязан строго 1 какой-то пользователь. И для того, чтобы задать такое ограничение на стороне бд. То есть, чтобы физически нельзя было добавить несколько записей с 1 и тем же имейлом, мы здесь эту настройку и указываем юник тру. Это значит, что
36: Абсолютно каждый имейл у каждого пользователя должен быть уникален. Последнее, что нам осталось, это наше поле id пометить аннотацией айди для того, чтобы дать понять, что это первичный ключ, и также пометить аннотации generates велью со стратегией айдентити для того,
37: Чтобы наша субд могла сама генерировать идентификаторы для каждого пользователя, когда мы будем создавать их и класть в нашу таблицу юзерс. Далее нам необходимо создать пустой конструктор без параметров. Это требование хибернейта для того, чтобы он мог правильно
38: Создавать объекты типа user. Старайтесь всегда об этом помнить, иначе это не будет работать. Далее. Нам необходимо определить ещё 1 конструктор, который будет удобен именно нам для того, чтобы мы могли в коде создавать новые объекты. Типа, user id,
39: Заполнять никогда не будем, потому что он будет генерироваться сам при добавлении в таблицу. Но нам нужен конструктор, с помощью которого мы сможем заполнить все остальные данные. Это имя, имейл, пароль и roll. Ну и конечно же, финальный штрих. Нам нужно добавить гетеры сетеры для всех полей.
40: Давайте их сгенерируем. Отлично. Наш энтити класс. User готов следующее, что нам необходимо, это создать юзера репозиторий именно с помощью этого юзера репозитория мы сможем взаимодействовать с бд и именно с сущностью юзер добавлять новых пользователей, удалять.
41: Существующих изменять существующих. И вообще, когда мы говорим про spring data, то каждому энтити классу, каждой сущности у вас должен соответствовать какой-то, который будет отвечать за взаимодействие с сущностями именно этого типа на уровне бд. Поэтому.
42: Так далее. Репозиторий.
43: Существующих, изменять, существующих и так далее. Вообще, когда мы говорим про spring data, то каждому энтити классу, каждой сущности у вас должен соответствовать какой-то репозиторий, который будет отвечать за взаимодействие с сущностями именно этого типа на уровне бд. Поэтому
44: Давайте в Папке репозиторий создадим новый интерфейс, который будет называться user репозиторий. Это у нас будет, как я уже сказал, interface. Мы должны его унаследовать от джипа репозитория. Так как это
45: Generic. Нам здесь нужно указать 2 параметра в качестве типов этого дженерика. 1 это сущность, с которой мы будем работать. Это у нас класс user и это именно наш user руку кичен энтити главное не перепутать. И 2 дженерик тайп это именно тип данных идентифи.
46: Внутри этой сущности напоминаю, что все айдишники у нас это Инты, то есть числовой тип данных. Поэтому здесь давайте укажем интеджер сам интерфейс. Нам нужно пометить аннотацией репозиторий для того, чтобы всем было понятно, что это именно репозиторий, что он относится именно
47: К уровню по работе с данными и все в таком духе. Теперь нам необходимо добавить соответствующий юзер сервис, который будет связующим звеном между контроллерами и между user репозиторием. Поэтому в пэкеджи сервис мы добавляем новый класс, который будет называться
48: User service его мы, конечно же, помечаем аннотацией, сервис в него нам также нужно заинжектить юзер репозиторий, поэтому указываем здесь наше прайвет, файнал поле, user репозиторий, юзер, репози.
49: Генерируем конструктор с этим полем и помечаем его аннотацией ауто вайр. Для того, чтобы выполнить внедрение всех необходимых зависимостей. Давайте также данный класс пометим аннотацией транзакшн для того, чтобы все методы, которые
50: Определены в этом классе, они являлись транзакционными, потому что напомню правило хорошего тона это помещать транзакции именно на методах сервиса, потому что обычно все операции внутри метода сервиса должны выполняться атомарно, потому что это какая-то 1 логи.
51: Операция, даже если она содержит в себе несколько походов в бд, например, извлечь данные, изменить данные, удалить или сохранить все эти вызовы бд, они должны выполняться строго в рамках 1 логической операции, которая как раз-таки и запрограммирована в сервисе. Поэтому
52: Все такие методы должны быть транзакционными. Теперь давайте в юзер сервисе определим новый метод, с помощью которого мы будем создавать новых пользователей, потому что нам этот метод понадобится при регистрации. Каждая регистрация это очевидно, создание нового пользователя в бд, поэтому
53: Пишем паблик войд сейф, передаём в качестве аргумента какого-то готового пользователя. Это юзер и в качестве реализации тут все достаточно просто. Мы обращаемся к репозиторию. У репозитория уже есть готовый метод сейф. Куда мы
54: Мы и передаём уже готового юзера, которого получили в качестве аргумента. Итак, вся основная логика по созданию новых пользователей у нас готова следующее, что нам необходимо сделать, это связать всю эту логику непосредственно с нашими веб страницами, чтобы пользо
55: Через браузер мог вызывать соответствующую логику, то есть регистрироваться для этого в паблик авторизейшн контроллере, который как раз-таки и отвечает у нас за процессы авторизации нам нужно определить новый пост метод, который как раз-таки под капотом и будет
56: Реализовывать весь процесс по регистрации новых. Поэтому объявляем этот самый метод public, возвращаемый тип string юзер. К примеру, вы можете назвать этот метод
57: Пользователей криэйт аккаунт.
58: Реализовывать весь процесс по регистрации новых пользователей, поэтому объявляем этот самый метод public, возвращаемый тип string криэйт, юзер аккаунт. К примеру, вы можете назвать этот метод
59: Абсолютно как угодно. Ставим фигурные скобки, и мы готовы написать реализацию. Но перед этим давайте свяжем данный метод с каким-то определённым урлом. В нашем приложении. Процесс регистрации должен происходить, когда пользователь на странице регистрации ввёл все необходимые данные и клик
60: На соответствующую кнопку. Это будет происходить при помощи отправки формы с веб страницы, а все формы, напоминаю, которые как-то изменяют состояние, они должны иметь метод post. Поэтому мы здесь должны указать аннотацию, пост маппинг и указать какой-то
61: Url урлы вызовах для того,
62: Например, smash регистрейшн, регистрейшн вот так вот, обратите внимание, что у нас здесь целиком и полностью совпадают, но тем не менее этот метод будет срабатывать при get.
63: Url, например, smash регистрейшн регистрейшн. Вот так вот обратите внимание, что у нас здесь целиком и полностью совпадают урлы, но тем не менее, этот метод будет срабатывать при get вызовах для того,
64: Чтобы отобразить соответствующую веб страницу, а этот метод будет срабатывать именно при пост вызовах, то есть при отправке формы, для того, чтобы выполнить нужное целевое действие, создать новый аккаунт. Понятное дело, что при регистрации мы должны получить набор каких-то полезных данных.
65: Code пользователя, то есть его имя, логин, пароль и так далее. Все, что он нам пришлёт для того, чтобы все это получить. Давайте откроем саму веб страницу и посмотрим, что именно мы будем получать
66: Итак, вот наша веб страница. Здесь у формы уже прописан метод пост, который как раз-таки будет вызываться на адрес слэш регистрейшн это именно тот урл, который мы определили внутри контроллера. Значит, наш контроллер действительно сможет обрабатывать все вызовы.
67: Формы.
68: Данной формы, то есть все отправки этой. Далее внутри этой формы нам будут отправлены данные с 3 инпутов, которые здесь перечислены в 1 инпуте. Параметр будет называться name. Это будет именно имя нашего пользователя. 2 параметр будет
69: Данной формы, то есть все отправки этой формы. Далее внутри этой формы нам будут отправлены данные с 3 инпутов, которые здесь перечислены в 1 инпуте. Параметр будет называться name. Это будет именно имя нашего пользователя. 2 параметр будет
70: Иметь название имейл. И логично, что здесь будет находиться введённый пользователем имейл и 3 такой квери параметр будет иметь название песпорт. И это будет пароль. Теперь в нашем контроллере нам необходимо связать все эти квери параметры с аргументами нашего метода. Давайте ещё
71: Ещё раз запомним это name имейл и пёсер, возвращаемся теперь в наш контроллер.
72: И теперь нам нужно перечислить все эти 3 аргумента. Это будет string, name, string, имейл и strings эсворд для того, чтобы связать все эти 3 аргумента непосредственно с query параметрами, которые придут нам.
73: Вместе с урлом, а точнее с http запросом. Нам нужно указать аннотацию. Реквест парам, поэтому давайте здесь её и напишем.
74: Напомню, что у requests парама есть параметр name, с помощью которого мы можем задать именно название квери параметра для того, чтобы спринг мог понять, с каким именно квери параметром нужно связать данное поле, если у нас название целиком и полностью совпадают у аргумента и
75: У квери параметра, то данный параметр name указывать необязательно. В нашем случае они совпадают целиком и полностью, поэтому мы просто можем указать данную аннотацию напротив каждого. Тогда спринг сам, что и с чем нужно. Также для того, чтобы у нас не получалось
76: Аргумента поймёт, связать.
77: У квери параметра, то данный параметр name указывать необязательно. В нашем случае они совпадают целиком и полностью, поэтому мы просто можем указать данную аннотацию напротив каждого аргумента. Тогда спринг сам поймёт, что и с чем нужно связать. Также для того, чтобы у нас не получалось
78: Настолько длинная строка для метода create user account правилом хорошего тона считается выполнять вот такие вот переносы на новую строку таким образом, все это выглядит более компактно, и при этом наглядно мы чётко видим, что у нас 3 уровня 3 строки. Это значит, что мы получаем на вход 3 параметра.
79: Все это находится на 1 уровне глаз, поэтому мы сразу можем видеть какие-то параметры. Это name имейл и песвот. Итак, теперь, когда мы получили все эти данные, нам необходимо создать пользователя со всеми этими данными. Для этого давайте определим переменную. User.
80: Выполняем импорт. Здесь опять же главное не ошибиться и импортировать нужный класс. После чего создаём новый объект юзера и нам нужно передать в этот конструктор все полученные значения. Это name. Это имейл, это пёсер и нам нужно
81: Также передать роль, так как через страницу регистрации могут создавать аккаунты только обычные пользователи, то мы всегда по умолчанию будем в качестве Роли передавать. User. Это значит, что зарегистрировался обычный пользователь. Теперь, когда сам объект типа user у нас готов, нам не
82: Необходимо положить все это в бд для того, чтобы это сделать, нам необходим юзер сервис, поэтому давайте добавим здесь соответствующее поле user service и заинжектил его в наш класс. Для этого генерируем конструктор и указываем аннотацию аутова.
83: Теперь, когда у нас есть необходимый бин юзер сервис, уже у него, мы можем вызвать метод сейф, который определили буквально пару минут назад и передаём только что созданного пользователя. После того, как была выполнена вся основная логика данного метода, нам нужно выполнить какой-то return, так как
84: Пользователь теперь уже существует в нашей бд. Это значит, что он теперь может залогиниться в систему, поэтому давайте выполним сейчас редирект на страницу Логина.
85: Чтобы пользователь мог сразу же ввести данные после регистрации и войти в систему, чтобы увидеть свой список дел и иметь возможность с этим списком дел взаимодействовать. Но не спешите радоваться. Логика в данном методе завершена ещё не полностью. Дело в том, что раньше в более старых
86: Версиях спринг секьюрити мы действительно могли хранить в бд пароль в том же виде, который пользователь нам и предоставил, то есть оригинальный пароль. Но это, конечно же, не есть хорошо, потому что если по каким-то причинам случится утечка данных из бд или кто-то получит
87: Доступ к нашей бд, он сможет увидеть все пароли всех наших пользователей, а значит, такой человек хакер. Он сможет иметь возможность заходить в любой личный кабинет, зная этот самый пароль, и выполнять там абсолютно любые действия, если конкретно для нашего web приложения, планировщик отдел.
88: Это не так критично, то для других более серьёзных веб приложений, например, для банков это, конечно же крайне и крайне, но хорошие привычки нужно прививать с самого начала, поэтому в большинстве случаев разработчики не хранят оригинальные пароли в бд, они хранят именно хэш.
89: Критично.
90: Это не так критично, то для других более серьёзных веб приложений, например, для банков это, конечно же крайне и крайне критично, но хорошие привычки нужно прививать с самого начала, поэтому в большинстве случаев разработчики не хранят оригинальные пароли в бд они хранят именно хэш.
91: От этого пароля, да и в более свежих версиях, спринг секьюрити, в том числе в той, которуююю используем именно мы spring security, заставляет нас хранить в бд не оригинальные пароли, а хэши этих паролей напомню, что хэширование переводится с английского как мясорубка это значит, что мы.
92: Пропускаем через какой-то специальный алгоритм исходные данные, а на выходе получаем просто какой-то набор из случайных символов. Это и есть хэш от того оригинального значения, который мы предоставили, и вся суть хэширования заключается в том, что если одно и то же оригина
93: Значение прогоняя через этот алгоритм хэширования, мы на выходе будем всегда получать один и тот же хэш, но при этом, зная сам хэш, восстановить оригинальный пароль практически невозможно. В целом это можно сделать, но это очень нетривиально и очень сложно.
94: Задача. Нужно иметь целую сеть из очень мощных компьютеров. Нужно найти лазейку в алгоритме хэширования, а также иметь большое количество паролей, сгенерированных по данному хэш алгоритму. И, имея совокупность всех этих данных, вы действительно можете попытаться взломать данные
95: Алгоритм и выполнить обратный процесс из хэша, научиться восстанавливать оригинальный, но, как я уже говорил, это крайне и крайне сложно, поэтому механизм хэширования это достаточно клёвый способ защиты от утечки данных из вашей бд для того, чтобы заставить
96: Пароль.
97: Алгоритм и выполнить обратный процесс из хэша, научиться восстанавливать оригинальный пароль. Но, как я уже говорил, это крайне и крайне сложно, поэтому механизм хэширования это достаточно клёвый способ защиты от утечки данных из вашей бд для того, чтобы заставить
98: Нас использовать такие механизмы хэширования спринг в security конфиге заставил нас определить bin песвот энкодера это как раз-таки и есть bin, который будет заниматься хэшированием данных, мы предоставляем ему какую-то оригинальную строку, он
99: Нам выдаёт хэш для этой строки. Поэтому в нашем контроллере, когда мы сохраняем пользователя, нам нужно сохранять пользователя не с оригинальным паролем, который он предоставил, а нужно взять хэш от этого пароля. Для того, чтобы это сделать, нам нужно также заинжектить бин.
100: Elsword, энкодера, поэтому пишем private final.
101: Elsword, энкодер давайте удалим данный конструктор и перегенерирует его заново уже с 2 аргументами и, конечно же, не забываем пометить его аннотацией аутова для того, чтобы внедрение зависимостей работало и вот теперь.
102: Теперь, когда у нас есть необходимый бин, который отвечает за хэширование, мы теперь можем оригинальный пароль захэшировать. Давайте создадим новую переменную, которая будет называться encoded песвот, то есть закодированный пароль, мы обращаемся к песвот энко.
103: Вызываем метод encode и можем передать сюда любую строку. Например, наш пароль, который предоставил пользователь. И вот именно этот encoded песвот. То есть хэш от пароля мы используем для создания нового пользователя нового объекта типа user.
104: Это значит, что и в бд мы также будем хранить хэш, а не оригинальный пароль. И теперь мы действительно смело можем сохранять в бд этого самого пользователя, ну или можем вообще не выносить все это в отдельную переменную, а прям new user передать в метод сейф. Давай.
105: Так и сделаем. Вот такая вот реализация нашего метода. Create user account у нас получилась. Давайте теперь запустим наше приложение и попробуем на странице регистрации создать новый аккаунт и убедимся, что у нас создалась необходимая таблица в бд и также
106: Появилась Нужная запись, которая подтвердит, что у нас действительно получилось создать новый аккаунт именно с помощью веб страницы. Итак, наше веб приложение стартануло. Открываем вкладку датабейс. Делаем здесь рефреш хибернейт должен был создать за нас новую таблицу.
107: Она действительно появилась, это таблица users. Давайте проанализируем состав колонок в этой таблице. Во первых, это id с типом integer. Здесь висит золотой ключик. Это значит, что это primary key. Далее у нас есть такие колонки, как имейл, нейм и песпорт. Все
108: Они имеют тип данных varchar, но у них немножко разные ограничения по длине. Это 30, 20 и 30 символов. Все 3 колонки являются у нас нот налл, потому что здесь у них нарисован вот такой вот кружочек. И при этом имейл является уникальным, потому что у него здесь горит вот такая вот
109: Синенькая плашка, давайте откроем саму таблицу и убедимся в том, что у нас здесь пока нет никаких данных. Теперь переходим в браузер и открываем страницу с регистрацией новых пользователей. Итак, вот у меня открылась страница регистрации. Напомню, что у нас в контроллере определённо 2
110: Маппинга для урла. Слэш регистрейшен только 1 для http get метода, а другой для http, post method. Так вот, немножко поясню, когда вы в адресной строке браузера вбиваете какие-то урлы. Например, smash registration. То в этом случае браузер
111: Под капотом отправляет именно запрос с http методом get. Именно поэтому, когда мы указываем слэш регистрейшн, у нас открывается веб страница, потому что мы контроллер запрограммировали. Именно так мы там использовали аннотацию. Гетт маппинг это значит, что
112: На любые гет запросы мы будем отображать именно веб страницу, поэтому мы и получаем её здесь. Окей, с этим вроде как понятно. Давайте попробуем заполнить все поля и создать нового. Я здесь напишу. Артём имейл будет, к примеру,
113: Пользователя.
114: На любые гет запросы мы будем отображать именно веб страницу, поэтому мы и получаем её здесь. Окей, с этим вроде как понятно. Давайте попробуем заполнить все поля и создать нового пользователя. Я здесь напишу. Артём имейл будет, к примеру,
115: Тест.
116: Собака джимэйл, точка ком и пароль у нас будет от 1 до 8, 1, 2, 3, 4, 5, 6, 7, 8. Так как у данного инпута в качестве тайпа я указал песвот, то в данном случае браузер автоматически скрывает все то, что я ввожу.
117: Тест собака, джимэйл точка ком и пароль у нас будет от 1 до 8, 1, 2, 3, 4, 5, 6, 7, 8. Так как у данного инпута в качестве тайпа я указал песвот, то в данном случае браузер автоматически скрывает все то, что я ввожу.
118: В данное поле для того, чтобы это никто не видел, потому что подразумевается, что это какая-то конфиденциальная информация. Но просто поверьте мне на слово, что я здесь ввёл именно цифры от 1 до 8. Теперь давайте кликнем на кнопку, по которой должна произойти отправка формы. Итак, нас почему-то переки.
119: На страницу с ошибкой. Давайте откроем айде и попробуем разобраться в том, что же произошло. А здесь, в логах нашего приложения, я вижу, что случилась. Эскьюэль ошибка, которая говорит о том, что мы предоставили какое-то слишком длинное значение, у которого тип данных
120: Это строка, то есть набор символов и с ограничением в 30 символов у нас таких колонки 2. Это имейл и песпорт. У обоих ограничение стоит в 30. Но имейл мы точно предоставили меньше чем 30 символов. Значит, проблема у нас в колонке песпорт, и это действительно скорее.
121: Символов.
122: Это строка, то есть набор символов и с ограничением в 30 символов у нас таких колонки 2. Это имейл и песпорт. У обоих ограничение стоит в 30 символов, но имейл мы точно предоставили меньше чем 30 символов. Значит, проблема у нас в колонке песпорт, и это действительно скорее.
123: Скорее всего так, потому что пароль, который мы предоставили от 1 до 8 цифры, это 8 символов. Но не забывайте, что данный пароль мы прогоняем через песпорт энкодер, который должен предоставить хэш от этого пароля. Подозреваю, что этот хэш достаточно длинный, и он, скорее всего, не влез.
124: Нам.
125: Скорее всего, так, потому что пароль, который мы предоставили от 1 до 8 цифры, это 8 символов. Но не забывайте, что данный пароль мы прогоняем через песпорт энкодер, который должен предоставить нам хэш от этого пароля. Подозреваю, что этот хэш достаточно длинный, и он, скорее всего, не влез.
126: В эти 30 символов. Поэтому предлагаю для данной колонки увеличить размерность. Давайте перейдём в наш энтити класс. User и для песвот укажем здесь не 30, а, допустим, 60 символов. Теперь просто напросто перезапускаем наше приложение. В этом случае хибернейт должен
127: Увидеть это обновление и должен нашу колонку привести к соответствующим изменениям, к соответствующему ввиду. Давайте выполним реконнект.
128: И мы видим, что как будто бы хибернейт этого не сделал. Но в принципе, ладно, не беда. Давайте в этом случае удалим данную таблицу, как будто её нет вообще, и перезапустим приложение заново. В этом случае хибернейт уж точно должен создать новую таблицу.
129: В соответствии со всеми настройками, которые мы здесь указали, приложение запустилось. Давайте выполним реконнект. Мы видим новую таблицу users, и у неё u колонки песвот. Теперь действительно ограничение стоит в 60 символов. Значит, мы можем смело переходить.
130: Браузер и попытаемся создать нового пользователя ещё раз. Итак, вот веб страница, давайте снова перезаполним данные я указываю здесь Артём, емейл тест, собака gmail дотком и пароль снова цифры от 1 до 8. Итак.
131: Апп. Смотрите, нас перебросило на страницу Логина точно так же, как мы запрограммировали метод в нашем контроллере. После того, как создали нового пользователя, делаем редирект, давайте откроем айде и саму таблицу users, проверим, что новый пользователь действительно появился. Итак,
132: Вот у нас таблица users айдишник 1 имейл тест джимейл точка ком. Имя Артём. Роль 0, которая соответствует пользователю потому что это у нас еннам и пароль вот такой вот указанн конечно же в форме я такой пароль не указывал, это значит
133: Что наш пасворд энкодер действительно работает. Он взял мой пароль цифры от 1 до 8 и превратил в хэш. Мы теперь в бд храним именно хэш паролей наших пользователей, что, конечно же, очень и очень круто, потому что это повышает безопасность нашего web приложения. Поздравляю.
134: Процесс регистрации готов. Теперь самое время перейти к реализации процесса Логина. Давайте вернёмся к презентации и обсудим с вами требования к форме Логина. Все дело в том, что когда мы используем спринг секьюрити, то процесс регистрации новых пользователей
135: Он ложится на плечи разработчиков этого веб приложения spring security, за это вообще никак не отвечает, но зато процесс Логина он как раз-таки ложится на плечи именно spring security, поэтому в этом случае нам практически ничего делать не нужно, все это за нас будет выполнять.
136: Spring security. Под капотом 2 вещи, которые от нас требуются. Следующие. 1. Это нужно внести дополнительные настройки в классе секьюрити конфиг, чем мы скоро займёмся. И 2, это правильно настроить форму, которая будет выполнять логин пользователей. Вот.
137: Конкретно сейчас мы поговорим про 2, про требования к форме Логина итак, поехали такая форма обязательно должна иметь метод пост. Против этого не попрёшь у spring security вот такие вот требования, которым обязательно нужно следовать, это нужно просто запомнить 2.
138: Форма обязательно должна делать запрос на url, который ожидает спринг секьюрити по умолчанию это smash логин то есть смотрите точно так же, как мы в контроллерах делаем какие-то методы и добавляем к этим методам маппинги на урлы спринг секьюрити уже предоставляет
139: Готовый обработчик всех запросов на адрес слэш, логин с методом пост. То есть если мы отправим такой запрос, то его обработает за нас спринг секьюрити и выполнит всю необходимую логику для того, чтобы залогинить пользователя в систему. Наша задача просто в форме.
140: Которую мы отправляем с веб страницы. Правильно задать все настройки для того, чтобы запрос улетел именно spring security, а он уже этот запрос правильно обработал и как здесь правильно написано по умолчанию такой url это smash логин. Но тем не менее в security конфиге мы данный url?
141: Можем изменить на любой другой короче говоря, форма на веб странице с логином должна выглядеть примерно следующим это action, splash, логин и метод пост. Все достаточно 3 требование форма обязательно должна в качестве параметров передавать.
142: Образом просто
143: Можем изменить на любой другой короче говоря, форма на веб странице с логином должна выглядеть примерно следующим образом это action, splash, логин и метод пост все достаточно просто 3 требование форма обязательно должна в качестве параметров передавать.
144: User name и песвот название параметров можно переопределить, делается это, конечно же, также в security конфиге дело в том, что для того, чтобы выполнить процесс Логина, спринг секьюрити требует от нас идентификатор пользователя и пароль от его учётной записи.
145: Это значит, что форма, которая будет отправляться на веб странице Логина, она обязательно должна содержать эти параметры, и именно с такими названиями user name и песвот, потому что spring security ожидает именно эти параметры, но наименование этих параметров, как здесь, напи.
146: Писано и, как я уже говорил, можно переопределить. Короче говоря, инпуты по умолчанию должны выглядеть следующим образом. 1 input имеет name username, 2 инпут имеет name песпорт тайпы. Вы, конечно же, можете указывать какие угодно. Это на процесс Логина никак не влияет.
147: Итак, теперь, после того, как мы с требованиями к форме Логина разобрались, давайте перейдём в id и донастроим секьюрити конфиг итак, вот класс секьюрити, конфиг здесь, перед строкой end build, нам нужно добавить ещё 1 настройку, для этого мы указываем просто.
148: Теперь вызываем метод форм логин. Тем самым мы даём понять, что мы сейчас будем задавать настройки именно для процесса Логина, именно для формы Логина. 1, что нам нужно сделать, это сообщить спринг секьюрити. По какому адресу вообще будет открыва.
149: Веб страница с логином, которую мы предоставляем сами для этого, пишем логин, пейдж, и здесь нам в качестве строки нужно указать относительный путь, по которому открывается соответствующая страница Логина это smash. Логин. Давайте поясню, зачем мы здесь это указываем.
150: Дело в том, что если мы будем пытаться получить доступ к каким-то закрытым, защищённым страницам, к приватным ресурсам, и если spring security будет видеть, что пользователь вообще не залогинен в систему, поэтому он не понимает у этого пользователя, который пытается попасть на эту.
151: Страницу. У него туда есть доступ или нет. Нужно залогиниться, чтобы это понять, то в таком случае спринг секьюрити будет автоматически перенаправлять все такие запросы на страницу Логина. Это крайне и крайне удобно. Абсолютно все веб сайты работают по Такому принципу. Если вы пытаетесь перейти на-ка,
152: Какую-то закрытую странницу вас автоматически перенаправят на страницу Логина и попросят войти в систему. Далее, что мы указываем? Это уже знакомый нам метод пермит ол, который обозначает, что данный адрес слэш логин, он будет доступен абсолютно любым пользователям.
153: Даже анонимным, которые не залогинены в систему, что логично, потому что страница, чтобы залогиниться в систему, она должна быть доступна вообще всем, даже незалогиненным. Кстати, указав здесь данную настройку, вот эту вот запись, слэш, логин, мы, по идее, можем удалить, потому что
154: Мы эту настройку теперь указываем здесь. Далее в презентации, в требованиях к форме Логина я говорил, что наша форма должна обязательно предоставить 2 параметра. Это username и песвот. И также я говорил о том, что данные параметры наименования для этих параметров мы можем изменить
155: Делается это с помощью следующих методов. Мы здесь указываем юзернейм параметр и в качестве значения мы можем передать любую строку. Вот то значение, которое мы сюда укажем. Например, там сдф. Вот именно так должен называться input теперь потому
156: Что именно этот параметр с названием сдф спринг секьюрити будет ожидать при вызове метода слэш логин с post методом, то есть, написав здесь сдф, мы должны перейти на страницу Логина.
157: И в нашей форме слэш логин у импута Логина. Мы здесь должны использовать не имейл, а сдф. Тогда это будет работать. Тоже самое касается и пароля. Но так как сдф я использовать, понятное дело, не хочу. Меня больше устраивает название параметра имейл, а не
158: Дефолтный юзернейм, потому что по параметру имейл я как-то больше понимаю, какие именно значения будут находиться в этом инпуте, потому что username это такое достаточно общее, достаточно абстрактное название в качестве юзернейма, может быть и просто логин какой-то, может быть и имейл может
159: Быть и номер телефона. Указав имейл, я чётко даю понять, что это именно почтовый адрес, поэтому, указав здесь имейл для того, чтобы все это работало в security конфиге, я здесь также должен подсказать спринг секьюрити, что логин пользователя user.
160: Name он теперь должен ждать из квери параметра с названием имейл. Ну и для пароля также есть соответствующий метод, который называется песвот параметр. Здесь вы можете передать любое наименование для параметра пароля. Мы на нашей странице логин пейдж используем в качестве названия.
161: Для данного импута песвот по умолчанию, он также песвот, поэтому мы здесь ничего не указываем. Данный метод мы не переопределяем, но при желании, конечно же, можем. И последнее, что нам нужно указать, это дефолт сексес урл. Здесь в качестве строки мы можем ука.
162: Любой url, на который спринг сделает редирект. Если пользователь будет успешно залогинен в систему, я после успешного Логина в систему хочу перенаправлять пользователей на страницу. Слэш аккаунт это именно адрес, по которому будет отображаться список дел. Что та
163: Также кажется достаточно логичным. Здесь также есть множество других полезных настроек, с которыми вы можете ознакомиться сами и погуглить, что каждая из них делает. Я же продемонстрирую вам лишь несколько из них. Например, если в процессе Логина произошла какая-то ошибка, к примеру, пользователь
164: Предоставил неправильный пароль. Вы можете указать url, на который нужно отправить пользователя. Если такая ошибка случилась, делается это при помощи метода Фейлер урл. То есть здесь вы можете указать какой-то адрес, на который спринг секьюрити сделает редирект при неуспешном логине
165: Если здесь ничего не указать, то по умолчанию спринг секьюрити будет делать редирект. В этом случае на ту же страницу слэш логин, только он добавит вот такой вот get параметр эрр. Имейте этот момент ввиду. Далее, как я уже говорил, мы можем переопределить
166: Url, на который нужно отправлять post запросы, то есть при сабмите формы Логина, мы можем переопределить урл, который спринг секьюрити будет ожидать по умолчанию. Это smash логин, но мы можем также его переопределить при помощи метода.
167: Вот он, логин процессинг url мы можем здесь написать что угодно например, smash сдф в этом случае на нашей странице логин пейдж у формы вместо Логина мы также должны написать слэш сдф именно по Такому урлу спринг секьюрити будет ожидать.
168: Все запросы для того, чтобы выполнить логин, но никакой сдф нам не нужен, логин нам более чем подходит, поэтому в security конфиге данный метод мы также не и url если случилась ошибка, мы также не предоставляем, потому что перенаправление на login error.
169: Переопределяем.
170: Все запросы для того, чтобы выполнить логин, но никакой сдф нам не нужен, логин нам более чем подходит, поэтому в security конфиге данный метод мы также не переопределяем и url если случилась ошибка, мы также не предоставляем, потому что перенаправление на login error.
171: Нас в принципе устраивает вот в принципе и все все настройки для процесса Логина мы предоставили после всех этих манипуляций логин теперь будет работать, и spring security под капотом будет выполнять всю ту магию, которая происходит, собственно, при логине, но нуж.
172: Нужно всегда помнить если существует логин, то также должен существовать и логаут для того, чтобы пользователь имел возможность выйти из своего личного кабинета, настраивается такой логаут следующим образом мы на новой строке также пишем n, после чего пишем лога.
173: Тем самым даём понять спринг секьюрити, что теперь все настройки будут предоставляться именно для логаута на базовом уровне. Эти настройки, они достаточно примитивные. Нам здесь нужно указать в 1 очередь логаут урл. То есть это тот адрес, на который нужно выполнить
174: Именно get запрос для того, чтобы пользователь вышел из системы, точнее, который обработает спринг секьюрити и специально принудительно сделает разлогин для этого пользователя, который перешёл по этому пути классический url для этого это, конечно же, просто логаут после
175: Этого мы, конечно же, должны вызвать пермит Оол для того, чтобы данный url, он был доступен абсолютно всем пользователям, даже те, которые не вы также можете самостоятельно посмотреть, какие здесь также доступны дополнительные методы для того, чтобы более тонко
176: Залогинены.
177: Этого мы, конечно же, должны вызвать пермит Оол для того, чтобы данный url, он был доступен абсолютно всем пользователям. Даже те, которые не залогинены. Вы также можете самостоятельно посмотреть, какие здесь также доступны дополнительные методы для того, чтобы более тонко
178: Настроить процесс логаута, но базовые настройки выглядят именно вот так. К примеру, есть такой метод, как логаут success url? То есть, например, если выход из личного кабинета произошёл успешно, мы можем указать здесь url, на который спринг секьюрити перенаправит?
179: Такого человека, если я правильно помню, и мы не указываем никакой логаут сакссес урл, то по умолчанию спринг секьюрити перебрасывает нас на страницу Логина вот с таким вот get параметром логаут или что-то вроде этого нас такое.
180: Введение в целом тоже устраивает вы разлогинились, вас сразу же перебрасывает на страницу Логина, поэтому мы здесь никаких дополнительных настроек указывать не будем итак, все настройки для security филтер чейн мы внесли, но тем не менее это пока что не все настройки в security конфиге, которые мы.
181: Должны сделать совсем скоро мы продолжим. А пока что давайте вернёмся к презентации и поговорим про такие понятия, как аутентификация и авторизация, потому что их очень и очень часто путают между собой. Итак, аутентификация это процедура проверки, подлин.
182: К примеру, путём сравнения введённого в форме сайта пароля пользователя с паролем, который хранится в бд, то есть с эталонным паролем, тот пароль, который хранится у нас в бд, это эталонный пароль пользователя, тот, который был указан при регистра.
183: И это единственно верный пароль, которому мы можем верить. Поэтому, когда пользователь на странице Логина предоставляет свой имейл и пароль под капотом, наша система должна сверить пароль этого пользователя, который он ввёл на форме с тем паролем, который хранится.
184: Бд. Это и есть проверка подлинности. Если эти пароли совпадают, то, значит, пользователь успешно прошёл аутентификацию. Наша система может быть уверена в том, что эти данные ввёл действительно тот человек, который является владельцем этого аккаунта, потому что
185: Он по каким-то причинам знает пароль. 2 понятие это авторизация, это предоставление определённому пользователю прав на выполнение определённых действий в приложении, то есть простыми словами. Когда пользователь прошёл аутентификацию, то в на
186: Нашей системе хранится также информация о том, какими ролями в системе обладает данный пользователь. И вот процесс авторизации это как раз-таки и есть процесс назначения этому пользователю всех этих ролей, которые ему соответствуют и после назначе.
187: Этих ролей. Пользователь теперь действительно может обращаться к различным приватным, защищённым ресурсам, и система будет проверять ту роль, которую мы ему назначили в процессе авторизации, с той ролью, которая необходима для доступа к этому приватному ресурсу. И если эти
188: Роли совпадают то система, то есть spring security, разрешит пользователю получить доступ к этому ресурсу например, открыть нужную веб. Помимо этих 2 понятий, есть также ещё 1 3, которое очень часто теряют из виду большинство разработчиков.
189: Страницу. Это понятие на
190: Роли совпадают, то система, то есть spring security, разрешит пользователю получить доступ к этому ресурсу, например, открыть нужную веб страницу. Помимо этих 2 понятий, есть также ещё 1 3, которое очень часто теряют из виду. Большинство разработчиков это понятие на
191: Называется идентификация. Это такая процедура распознавания неизвестного анонимного пользователя по какому-либо уникальному признаку идентификатору, к примеру, по емейлу или по номеру телефона и так далее. Когда пользователь зашёл на сайт, то
192: Наше приложение абсолютно не понимает, что это за пользователь, этот пользователь для системы аноним. И когда пользователь на странице Логина предоставляет свои данные, то есть имейл и пароль имейл, это как раз-таки и есть идентификатор этого пользователя, потому что по имейлу
193: Мы однозначно можем найти нужного пользователя в нашей бд и понять, что это за пользователь, какое у него имя возможно, фамилия, отчество, дата рождения, пол, пароль и все в таком духе. Поэтому весь процесс Логина под капотом состоит из этих 3 последователь.
194: Шагов. 1 шаг это именно идентификация, потому что по предоставленному идентификатору в случае нашего web приложения это имейл. Мы идём в бд. И по этому имейлу мы можем однозначно найти нужного пользователя, когда мы по имейлу
195: Пользователя определили, извлекли его из бд. Мы теперь чётко знаем, что именно это за пользователь. То есть он теперь идентифицирован. Далее выполняется процесс аутентификации. Мало того, что мы теперь знаем, что это за пользователь, нам теперь нужно убедиться на той стороне экра.
196: Действительно ли сидит владелец данного аккаунта, потому что имейл указать мог любой другой человек, поэтому, когда мы в процессе идентификации извлекли из бд данные об этом пользователе, мы также извлекли информацию об его эталонном пароле настоящем.
197: Оригинальном пароле. И в процессе аутентификации мы сравниваем пароль, который был введён на форме сайта с эталонным паролем. И если они совпадают, то мы убеждаемся, что этот человек действительно тот, за кого себя выдаёт. То есть он аутентифицирован. А так как этот человек теперь
198: Аутентифицирован, то мы должны выполнить авторизацию, то есть назначить этому пользователю соответствующие ему права Роли. Вся информация также может храниться у нас в бд. Поэтому, когда мы на процессе идентификации получили пользователя, мы также знаем, какие Роли нужно назначить этому.
199: Пользователю, если он успешно пройдёт процесс аутентификации. И вот когда все эти 3 этапа пройдены, можно считать, что пользователь залогинен в систему, и теперь он может выполнять абсолютно любые действия в этом приложении. Конечно же, если у него есть доступ к нужным,
200: Приватным ресурсом, потому что если пользователь обычный юзер, то он, конечно же, не может открыть страницу для администрирования, потому что у него нет соответствующих прав, несмотря на то, что он залогинен в систему. Давайте теперь, понимая все эти 3 явления, такие как идентификация, аутентификация.
201: И авторизация опишем весь наш процесс Логина по шагам. Итак, допустим, пользователь зашёл на наш веб сайт. У него открылась страница Логина. На этой странице пользователь вводит свой логин и пароль и отправляет запрос на сервер при получении такого
202: Запроса в 1 очередь запускается процедура идентификации. Если пользователь успешно идентифицирован. То есть мы действительно нашли такого пользователя в бд и понимаем, кто это то запускается процесс аутентификации, то есть проверка подлинности предоста
203: Оставленного пароля. Если пользователь успешно аутентифицирован, то есть он предоставил корректный пароль, то ему назначаются доступные для него Роли, то есть выполняется процедура авторизации. Если же пользователь не аутентифицирован, то есть он предоставил какой-то неправильный пароль, то будет
204: Выброшена соответствующая ошибка. Например, на странице Логина отобразится сообщение о том, что вы ввели неправильный пароль, но если пользователь все-таки авторизован, ему теперь назначены нужные Роли. Он теперь может выполнять различные запросы к защищённым приватным ресурсам и при доступе
205: К любому Такому защищённому приватному ресурсу происходит проверка ролей для данного пользователя. Если его Роли подходят для доступа к этому ресурсу, он, этот доступ получает. Если его Роли не подходят, то он этот доступ не получает, несмотря на то, что он залогинен.
206: Значит, авторизован в системе. Короче говоря, есть 2 новости. 1 хорошая, a2 не очень хорошая новость заключается в том, что этапы по аутентификации и авторизации берет на себя целиком и полностью спринг секьюрити. A2 новость, которая не очень она
207: Заключается в том, что самый 1 этап, то есть идентификация, она возлагается на наши плечи, на плечи разработчиков, поэтому в security конфиге нам нужно здесь объявить ещё 1 bin, с помощью которого мы сможем идентифицировать пользователей.
208: Для этого нам нужно объявить бин с типом данных user details сервис давайте этим и займёмся мы здесь пишем паблик возвращаемый тип у нас будет user details сервис это вот этот вот интерфейс, который находится в spring фреймворке, исполь.
209: Его теперь придумываем. Название для нашего бина. Пусть это будет также user details сервис и теперь пишем реализацию, так как user details сервис это интерфейс, то мы не можем создать объекты данного типа.
210: Но мы можем здесь объявить анонимный класс. Напомню, что анонимный класс это когда мы, по сути, наследуемся от какого-то класса или интерфейса и прям тут же на месте переопределяем какие-то методы или определяем какие-то методы этого интерфейса или класса, поэтому пишем ретерн.
211: New user details.
212: Сервис. У данного сервиса есть всего лишь 1 метод, это load user by username нам предоставляется какой-то username, и нам нужно по этому юзернейму предоставить более полноценную полную информацию.
213: New user details. Сервис. У данного сервиса есть всего лишь 1 метод, это load user by username. Нам предоставляется какой-то username, и нам нужно по этому юзернейму предоставить более полноценную полную информацию.
214: О данном пользователе и вернуть её в виде вот такого вот класса. User details. И так как этот метод, он единственный в интерфейсе юзер details сервис, нам только его и нужно. Именно с помощью этого метода. Лоад юзер, бай юзер нейм мы и реализуем процед.
215: Реализовать.
216: О данном пользователе и вернуть её в виде вот такого вот класса. User details. И так как этот метод, он единственный в интерфейсе юзер details сервис, нам только его и нужно реализовать именно с помощью этого метода. Лоад юзер бай юзер нейм мы и реализуем процед.
217: Идентификации, которая выполняется самой 1. Когда пользователь ввёл на странице Логина свой имейл и пароль и отправил форму. Этот запрос получит и начнёт обрабатывать спринг секьюрити. Спринг секьюрити, в 1 очередь запускает процедуру идентификации. Он нахо
218: Bing вот с таким вот типом user details сервис и вызывает у него метод load user by user name, то есть тот, который мы сейчас и определяем в качестве аргумента спринг секьюрити, передаёт сюда тот самый имейл, который пользователь ввёл на странице Логина, и мы
219: Получается, своими усилиями должны найти информацию об этом пользователе с таким логином, то есть в нашем случае с и вернуть её спринг секьюрити. В частности, мы должны вернуть информацию об эталонном пароле для такого пользователя, а также набор
220: Таким емейлом ролей, которые нужно
221: Получается, своими усилиями должны найти информацию об этом пользователе с таким логином, то есть в нашем случае с таким емейлом, и вернуть её спринг секьюрити. В частности, мы должны вернуть информацию об эталонном пароле для такого пользователя, а также набор ролей, которые нужно
222: Будет этому пользователю назначить, если он успешно пройдёт процедуру аутентификации, то есть процедуру сверки подлинности паролей. Если же такого пользователя у нас в системе нет, то мы должны выбросить ошибку. User name not found эксепшн. В таком случае спринг секьюрити поймёт, что такого
223: Пользователя в нашей системе вообще нет. И логично, что залогиниться он также не может, так как все наши пользователи хранятся в бд, то для того, чтобы извлечь пользователя по юзернейму, нам, конечно же, нужно сходить в бд. Для этого нам понадобится user репозиторий, поэтому давайте данный компонент.
224: Здесь и объявим прайвет, файнал юзер, репозиторий, юзер, репозиторий. Давайте сгенерируем конструктор, укажем здесь аннотацию ауто вайр для того, чтобы внедрить сюда тот самый user репозиторий теперь.
225: Здесь нам необходимо с помощью юзера репозитория обратиться к бд и найти нужного пользователя по его юзернейму, который нам предоставил спринг. Этот user name это, конечно же, имейл, потому что на нашей странице Логина пользователь вводит именно имейл такого метода в джип.
226: Репозиторий, конечно, поэтому нам нужно объявить его. Переходим в user и здесь добавим новый. Напоминаю, что благодаря спринг, дата в джипа репозиториях, мы можем объявлять новые методы. Эйчкью эль, реализац.
227: Же нет вручную репозиторий метод и предоставлять
228: Репозиторий, конечно же, нет, поэтому нам нужно объявить его вручную. Переходим в user репозиторий и здесь добавим новый метод. Напоминаю, что благодаря спринг дата в джипа репозиториях мы можем объявлять новые методы и предоставлять эйчкью эль реализац.
229: С помощью аннотации квери для этих методов или именовать эти методы таким специальным образом, чтобы спринг дата по названию этого метода автоматически предоставляла реализацию, я предлагаю воспользоваться именно 2 способом, поэтому давайте объявим здесь новый метод.
230: В соответствии с нужными правилами именования, так как мы будем искать пользователя по имейлу. А имейл это у нас уникальная сущность. Это значит, что мы можем найти строго 1 такого пользователя, либо не найти вовсе. То есть нам из бд может вернуться нал. В этом случае нам
231: Конечно же, лучше предоставить ответ в виде опшинал, поэтому это здесь и указываем опшинал. Тип данных у нас будет. User импортируем нужный опшинал. И теперь мы готовы писать непосредственно название для самого метода, так как мы
232: Ищем пользователя, то и пишем find, так как нам нужен всего лишь 1 пользователь, то нам больше подходит название файнд бай. Поэтому пишем бай. Теперь мы должны указать поле, по которому мы будем искать пользователя. В нашем случае это имейл, потому что мы
233: Будем искать пользователя именно по его имейлу. И также я предлагаю дополнительно здесь написать игнор кейс для того, чтобы хибернейт, когда будет искать такого пользователя по емейлу, сравнивал эти емейлы регистронезависимо. То есть, если пользователь ввёл свой
234: Имейл капслоком, к примеру, то в нашей бд мы такого пользователя действительно найдём. Теперь здесь в качестве аргумента нам нужно указать, соответственно, аргумент string, имейл. Итак, наш метод готов. Теперь мы можем воспользоваться им в security конфиг классе, так как
235: Мы будем искать пользователя, давайте объявим здесь соответствующую переменную user импортируем нужный class, равно обращаемся к user репозиторию теперь у юзера репозитория, вызываем метод find by имейл, игнор кейс, и нам нужно
236: Предать имейл. Это и есть тот самый юзернейм, который мы получили в качестве аргумента, так как данный метод возвращает опшинал, то нам нужно этот опшинал, конечно же, правильно обработать. Делаем мы это с помощью метода орелс фроу. Для данного метода нам нужно предоставить
237: Лямбду, которая будет предоставлять нужный exception, который нужно выбросить. Если мы в бд ничего не нашли, саплаер у нас ничего на вход не принимает, поэтому указываем пустые скобочки стрелка и теперь нужно предоставить объект с типом рантайм эксепшн, который
238: Будет выброшен, если мы ничего не нашли в бд. Ошибку нам нужно выбросить, конечно же, вот такую вот, которая есть в сигнатуре у данного метода, чтобы спринг секьюрити понял, что именно произошло. То есть, что мы не нашли пользователя в бд, поэтому пишем здесь new user name
239: Not found эксепшн и здесь для данной ошибки мы можем воспользоваться конструктором и передать какое-то сообщение для этого. Давайте напишем следующее. User with имейл равно давайте добавим сюда непосредственно тот
240: Имейл, по которому мы пытались найти пользователя. Это будет user name плюс и пишем нот фаунд. Отлично готово. Ставим точка с запятой. Понятное дело, что такой длинный метод, он абсолютно не читается, поэтому предлагаю здесь выполнить перенос.
241: Строк файнд б mail, игнор кейс и, конечно же, Орёл строу вот так выглядит уже гораздо симпатичней после того, как мы нашли пользователя в бд. В качестве ответа нам нужно вернуть объект с типом user details у спринга есть свой собственный класс. User.
242: Который реализует данный интерфейс. User details. Поэтому нам нужно здесь вернуть объект типа user, но именно объект, спринг фреймворка, поэтому мы здесь пишем ретерн нью, создаём нового юзера. Нам нужен именно этот, который находится
243: Пакете спринг фреймворк security core user details так как мы в нашем методе уже использовали класс user это наш собственный юзер, то мы не можем импортировать данный класс, поэтому нам необходимо прописать здесь полный путь к этому классу это нормальное явление, поэтому не пугайтесь.
244: Теперь давайте посмотрим, какой конструктор у данного класса. Он просит, чтобы мы предоставили user name. Поэтому давайте его и предоставим. Или даже чтобы было наверняка. Давайте обратимся к юзеру, которого мы нашли, и обратимся у него к методу get имейл. Это и будет user name теперь.
245: Нам нужно предоставить пароль. Обращаемся к юзеру, которого нашли в бд, и также вызываем метод get песо. И 3, что требует данный конструктор, это коллекцию с какими-то ауторити. Это как раз-таки и есть набор ролей для данного пользователя.
246: Если этот пользователь пройдёт целиком и полностью процедуру аутентификации и авторизации, то ему будет назначен тот набор ролей, который мы здесь сейчас сюда передадим. Напоминаю, что внутри объекта user у нас зашита информация о той Роли, которая
247: Обладает данный пользователь. Поэтому мы здесь можем создать эту коллекцию. Допустим, это у нас будет сет для того, чтобы у нас Роли не дублировались. Тип данных будет simple гренте афорить. Импортируем сет на
248: Данную коллекцию как rose, то есть Роли, которые принадлежат данному пользователю конкретно. В нашем случае 1 пользователю может принадлежать только 1 роль, но в любых других приложениях может быть по другому. У пользователя может быть сразу несколько ролей. В нашем же случае просто пишем коллекшн.
249: Сингл тон, обращаемся к переменной user и извлекаем роль пользователя, так как roll пользователя это еннам, а у коллекции тип данных симпл гренте афорить, нам нужно еннам к этому типу преобразовать, поэтому здесь мы можем написать следующее.
250: New симпл грантед оофорит в качестве аргумента. Нам нужно принять просто какую-то строку с наименованием Роли для этого get ролл. Нам нужно вызвать метод name.
251: Вот теперь вот все готово. Теперь список этих ролей мы можем передать в конструктор, и тогда именно эти Роли будут назначены этому пользователю, если он успешно залогинится в систему. Но есть 1 очень и очень важное. Но когда мы передаём роль вот в объект,
252: Этого типа, то все эти Роли, они обязательно должны иметь префикс ролл андерскор. Это, к сожалению, немного запутанно, но тем не менее, такая вот реальность. Именно так работает спринг. Если наши енамы это в нашем случае просто юзер.
253: Просто админ то spring security под капотом оперирует именно вот такими форматами ролл юзер или, к примеру, role admin, поэтому к нашему енаму мы должны вот этот вот префикс ролл добавить вручную, если мы сделаем это прям в секьюрити.
254: Конфиги, например, напишем следующее ролл андерскор плюс и, соответственно, значение енама, то, согласитесь, выглядит это не сильно симпатично. А самое главное, мы всегда можем легко забыть, добавить этот префикс и
255: Запутаемся в том, какие Роли нужно указывать. Поэтому я предлагаю внутри нашего енама определить специальный метод, который для Роли будет возвращать именно объекты с типом симпл гренте Алферт, чтобы здесь не создавать его вручную. Для этого давайте откроем юзер.
256: Raw еннам, новый метод нас будет simple примеру to афорить к?
257: И теперь здесь мы можем объявить это у нас будет public возвращаемый тип у grandaddy, и назовём мы метод к. То есть мы преобразовываем наш еннам.
258: Raw еннам, и теперь здесь мы можем объявить новый метод это у нас будет public возвращаемый тип у нас будет simple grandaddy и назовём мы метод, к примеру, to афорить, то есть мы преобразовываем наш еннам к.
259: Какому-то указываем теперь фигурные скобки и в качестве реализации пишем следующее. Return new симпл гренте Алфарит как раз-таки здесь добавляем этот префикс ролл, обращаемся к this и получаем строковое представление на
260: Nam. Получается, что в этом случае благодаря этому методу всю логику по добавлению всех этих префиксов мы перенесли именно в сторону енама. Мы теперь можем просто вызывать этот метод, и у нас голова не будет болеть о том, какой префикс и куда нам нужно добавить. Поэтому давайте вер.
261: Вернёмся в security конфиг, и теперь здесь, вместо того, чтобы создавать этот объект сложный, мы можем обратиться user get ролл и теперь вызвать метод to афорить который преобразует еннам непосредственно в simple гренте, афорить который
262: Подходит в эту коллекцию. Кстати говоря, когда мы здесь настраивали секьюрити филтер чейн, и когда мы указывали эти методы, энд мэтчер указывали какой-то url и прописывали набор ролей, с которыми доступны будут эти приватные ресурсы, то spring.
263: Security этот префикс ролл добавлял за нас. Обратите внимание, что мы здесь просто передаём user или, к примеру, admin если мы перейдём в реализацию, то мы здесь увидим, что фигурирует вот такой вот role префикс если перейдём к нему, то увидим, что в конструкторе задаётся как раз-таки этот ролл.
264: Префикс, именно он под капотом будет использоваться и добавляться ко всем значениям, которые мы здесь передаём. Это как раз-таки и подтверждает мои слова о том, что спринг под капотом к каждой Роли, которую мы здесь передадим, будет добавлять этот префикс ролл. Поэтому он
265: Будет работать s ролл и для того, чтобы все это было совместимо друг с другом и правильно работало, и все эти настройки правильно применялись, нам нужно все это указывать в 1 виде и все вот эти вот префиксы добавлять также.
266: Юзер и role admin. Здесь, когда мы
267: Будет работать s ролл юзер и role admin, и для того, чтобы все это было совместимо друг с другом и правильно работало, и все эти настройки правильно применялись, нам нужно все это указывать в 1 виде и все вот эти вот префиксы добавлять также здесь, когда мы
268: Выполняем процедуру идентификации. Итак, давайте данный комментарий здесь уберём, здесь поставим точку с запятой, не забываем наш метод пометить аннотацией бин. И вот уже теперь можно сказать, что все необходимые настройки предоставлены, а значит,
269: Процесс Логина теперь будет работать. Давайте попробуем в этом убедиться, для чего перезапустим наше веб приложение.
270: Приложение стартануло. Давайте откроем браузер. Итак, вот у нас есть страница Логина, я пока что не залогинен в систему. Давайте я попробую перейти на страницу слэш аккаунт, которая является у нас приватной. Если я её открываю, то обратите внимание, что меня
271: Тут же перенаправила на страницу Логина. Это делает спринг секьюрити. Теперь автоматически, при попытке доступа к защищённому ресурсу он видит, что пользователь не залогинен в систему, он для системы аноним, поэтому тут же делает редирект на логин и говорит залогинься, потому
272: Что ты пытаешься получить доступ к защищённому ресурсу? Это 1. 2, что у меня, как вы видите, нет доступа к странице слэш аккаунт. Давайте попробую это выполнить ещё раз. Меня опять же перекинуло на страницу Логина. У нас в системе сейчас существует всего лишь 1
273: Пользователь у него имейл это тест собака джимэйл точка ком и пароль это цифры от 1 до 8, которые я здесь и указываю. 1, 2, 3, 4, 5, 6, 7, 8. Это должен быть именно тот пароль, который я указывал при регистрации. Итак,
274: Теперь я кликаю логин, и произошло о чудо я залогинился в систему, меня автоматически перекинуло на страницу слэш аккаунт, потому что именно этот адрес мы указали в security конфиге, и также у меня отображается эта страница, то есть она после Логина теперь.
275: Недоступно. Я действительно вижу список всех дел и могу с ними как-то взаимодействовать, например, добавлять новые записи, помечать их как выполненные или удалять. Так как нам с вами удалось все-таки победить процесс Логина. Давайте я попытаюсь ещё раз кратко объяснить, как все это рабо.
276: Работает в айде конфиг всем.
277: Для начала давайте перейдём в класс секьюрити. Итак, во первых, мы здесь задали настройки для Логина. Мы говорим, что страница с логином доступна по этому адресу, и эта страница доступна вообще для того, чтобы выполнить логин сприн.
278: Работает для начала давайте перейдём в айде в класс секьюрити конфиг. Итак, во первых, мы здесь задали настройки для Логина. Мы говорим, что страница с логином доступна по этому адресу. И эта страница доступна вообще всем для того, чтобы выполнить логин. Сприн
279: Security создаёт специальный обработчик этот обработчик отлавливает любые запросы, которые имеют пост http метод и отправляются на адрес слэш логин у всех таких запросов должно быть 2 квери параметра это параметр с названием.
280: Mail и параметр с названием песвот. Если форма отправлена верно? И этот обработчик, предоставленный спринг секьюрити, смог получить такой запрос, то, значит, выполняется вся та логика, которая в нём написана, а она включает в себя 3 шага идентификацию, аутентификацию и
281: Авторизацию. Если все эти 3 шага будут успешно выполнены, то это значит, что пользователь залогинен в систему и его нужно перебросить на этот адрес. Слэш аккаунт. Из всех этих 3 Шагов на наши плечи ложится только 1. Это идентификация, которую мы предоставляем с помощью
282: Этого метода лоад юзер бай юзернейм, потому что, когда spring security запустил под капотом в обработчике весь этот процесс, он начинает с 1 шага это идентификация, и именно мы должны предоставить механизм как по имейлу, идентифицировать пользователя и предоставить.
283: Все полные данные об этом пользователе. В нашем случае логика достаточно простая. Мы идём в бд и пытаемся найти такого пользователя по его логину, то есть по имейлу, если мы такого пользователя не нашли, то выбрасывается ошибка. User name not found эксепшн в этом случае.
284: Spring security просто прекратит весь процесс, и у нас останется отображаться страница, слэш, логин, но если эта ошибка не выбросилась и мы действительно нашли какого-то пользователя, теперь нам нужно предоставить полные данные об этом пользователе, в частности, набор ролей, которые.
285: Доступны данному, а также его логин и эталонный пароль. Мы предоставляем все эти данные и возвращаем вот такой вот комплексный объект, который будет использоваться на всех остальных шагах, таких как аутентификация и авторизация. Но все это будет
286: Пользователю.
287: Доступны данному пользователю, а также его логин и эталонный пароль. Мы предоставляем все эти данные и возвращаем вот такой вот комплексный объект, который будет использоваться на всех остальных шагах, таких как аутентификация и авторизация. Но все это будет
288: Происходить уже под капотом спринг секьюрити. Теперь, когда мы с точки зрения кода более подробно в этом разобрались, давайте перейдём к презентации. И здесь я попытаюсь ещё раз описать весь этот процесс, но уже схематично и в картинках, потому что я понимаю, что эта тема
289: Она достаточно сложная, понять и впитать в себя всю эту теоретическую информацию крайне, крайне сложно. Я прекрасно это понимаю, потому что сам когда-то проходил через этот процесс, поэтому и пытаюсь объяснить вам, как и что здесь работает с разных ракурсов и с точки зрения кода.
290: И схематично, и на словах, и так далее. Итак, погнали. Пользователь открыл в браузере страницу Логина. Там отображается вот такая вот форма, куда пользователь ввёл свой имейл и пароль, после чего он кликает на кнопку логин в результате этого
291: Происходит отправка формы по адресу слэш, логин с http методом post на сервер, на котором развёрнуто наше веб приложение, обработчик, который ловит все такие запросы по Такому адресу. И с таким http методом предоставляется именно spring
292: Security. Поэтому именно spring security ловит все такие входящие запросы для того, чтобы выполнить процесс Логина процесс Логина состоит у нас из 3 Шагов 1 это идентификация, когда мы по идентификатору, в нашем случае по имейлу должны
293: Определить вообще, существует ли такой пользователь в нашей системе. И если существует, то мы должны предоставить более подробную развёрнутую информацию об этом пользователе. 2 этап это аутентификация, этап, на котором происходит проверка подлинности, то есть
294: Мы сравниваем эталонный пароль, который находится у нас в бд для данного пользователя, с тем паролем, который пользователь сейчас ввёл на странице Логина. Если эти пароли не совпадают, то процесс Логина на данном этапе завершается. Пользователь не смог залогиниться в системе.
295: Потому что предоставил неправильный пароль. Но если пароли совпадают, значит, проверка подлинности прошла успешно, и мы переходим к 3 этапу. Это авторизация. Авторизация это назначение этому пользователю всех его ролей для того, чтобы он смог теперь
296: Получать доступ к определённым приватным страницам, к приватным ресурсам теперь давайте более подробно, но тем не менее схематично разберём каждый из этих этапов, как выглядит весь этот процесс, весь этот flow. Начинаем мы с самой 1 процедуры это идентификация итак, когда
297: Запускается процесс идентификации, то напоминаю, что это единственный из этапов, который должны реализовать именно мы как разработчики, потому что 2 и 3 этап берет на себя спринг секьюрити когда запущен процесс идентификации, то spring security обращается к.
298: User details сервису напоминаю, что bin с таким типом мы с вами указывали в security конфиг классе, именно у этого бина есть единственный метод, это load, user by username, спринг секьюрити предоставляет нам username, в нашем случае это имейл пользователя.
299: Его идентификатор. И по этому идентификатору мы должны найти этого пользователя в нашем хранилище данных и вернуть более полную информацию про этого, которая будет использоваться на всех последующих этапах. Поэтому user details сервис в соответствии с той логи,
300: Пользователя.
301: Его идентификатор и по этому идентификатору мы должны найти этого пользователя в нашем хранилище данных и вернуть более полную информацию про этого пользователя, которая будет использоваться на всех последующих этапах. Поэтому user details сервис в соответствии с той логи.
302: Которую мы предоставили, он обращается непосредственно к базе данных для того, чтобы найти такого пользователя по его имейлу. Если мы такого пользователя не нашли, то мы выбрасываем ошибку. User name not found эксепшн в этом случае весь процесс Логина.
303: На данном этапе. Но если мы такого пользователя в бд, то теперь нам необходимо сформировать объект с типом user details, который мы должны вернуть из метода лоад юзернейм внутри user details сервиса
304: Прекращается. Нашли юзер бай.
305: На данном этапе прекращается. Но если мы такого пользователя в бд нашли, то теперь нам необходимо сформировать объект с типом user details, который мы должны вернуть из метода лоад юзер бай юзернейм внутри user details сервиса данное.
306: Объект состоит всего лишь из 3 составляющих. Во первых, это непосредственно логин нашего пользователя, его user name. В нашем случае это имейл. Во вторых, это эталонный пароль, который находится у нас в бд, но напоминаю, что в бд мы не храним оригинальные
307: Пароли мы храним всегда хэш от этих оригинальных паролей, поэтому в user details будет находиться именно хэш пароля, и также мы должны предоставить набор ролей, которые данному пользователю нужно присвоить, если он успешно пройдёт процесс аутентификации.
308: После того, как мы предоставили такой объект user details, то он возвращается из метода лот юзер бай юзернейм, и на этом процедура идентификации завершается. Спринг секьюрити переходит ко 2 шагу. Это аутентификация, при этом спринг секьюрити, конечно же, владеет.
309: Всей той информацией, которую мы предоставили с помощью user details. Это эталонная информация о пользователе, который сейчас пытается войти в систему. Помимо этой эталонной информации, спринг секьюрити, конечно же, также хранит и данные с формы, то есть непосредственно
310: На то, что пользователь ввёл на странице Логина какой-то имейл и какой-то пароль. Итак запускается процедура аутентификации. Напоминаю, что это процедура, в рамках которой происходит проверка подлинности, а происходит она за счёт того, что мы сравниваем это
311: Пароль, который хранится в user details, тот, который мы извлекли из бд, с тем паролем, который пользователь по факту предоставил на странице Логина. Но вот незадача на странице Логина пользователь ввёл свой реальный пароль а в бд хранится именно.
312: Хэш пароля и поэтому в user details мы предоставили также именно хэш от этого оригинального пароля как быть в этом случае? Ответ на самом деле достаточно прост. Под капотом спринг секьюрити используют бин песпорт энд кодер, который также создали мы в классе секьюрити конфиг.
313: И как раз с помощью этого бина при регистрации пользователя мы также захешировал оригинальный пароль. И именно этот хэш мы и сохранили в бд. Теперь спринг секьюрити должен выполнить обратную процедуру. Итак, задача песвот энкодера сейчас это сравнить 2 пароля это
314: Лонный с тем, который по факту предоставил конкретно. Сейчас пользователь песпорт энкодер берет хэш пароля из user details это тот самый эталонный, то есть правильный пароль, поэтому мы помечаем его зелёным, потому что он эталонный, после чего песпорт энкодер извлекает.
315: Пароль, который был получен из формы. Именно этот пароль теперь будет использоваться для сравнения с эталонным. Поэтому мы помечаем его как жёлтый, потому что мы пока что не знаем этот пароль верный или неверный. Конечно же, мы не можем сравнить между собой просто пароль и хэш пароля, поэтому
316: Нам необходимо из пароля с помощью песвот энкодера получить хэш этого пароля. Напоминаю, что все хэш функции, все хэш алгоритмы, они работают по Такому принципу, что для одних и тех же входных данных всегда будет генерироваться один и тот же хэш код. Поэтому, если при
317: Регистрации. Пользователь указал 1 пароль и при логине указал точно такой же пароль, то для них будет сгенерирован один и тот же хэш. Поэтому в данном случае, если пользователь на странице Логина действительно указал правильный пароль, то 2 этих хэша, они совпадут, будут равны.
318: Друг с другом, и именно поэтому spring security приходит к выводу, что проверка подлинности пройдена успешно, а значит, и процедура аутентификации она у нас выполнена, поэтому мы переходим к следующему этапу это авторизация, когда запускается процесс авторизации.
319: То под капотом происходит обращение к Такому достаточно загадочному классу, как security context, холдер с помощью данного класса мы можем получить информацию о том, какой именно пользователь конкретно сейчас выполняет запрос к серверу, что это за пользователь, какой у него логин.
320: Какой у него набор ролей и так далее. Вся эта информация о текущем пользователе, она хранится в таком объекте, как аутентификейт, но так как на момент Логина пользователь ещё не вошёл в систему, то и аутентификейт объекта для него ещё пока что не существует.
321: Поэтому именно этот объект спринг секьюрити и создаёт для нас на процессе авторизации для данного объекта нужно предоставить логин пользователя, а также набор ролей, которые присущи этому пользователю, поэтому spring security именно из user details берет.
322: Роли и назначает их в этот объект аутентификейт. Это значит, что теперь тот пользователь, который только что выполнял процедуру Логина, он авторизован в системе, потому что для него создан объект аутентификейт и ему назначен определённый набор ролей.
323: А значит, теперь можно считать, что процедура авторизации успешно выполнена спринг секьюрити делает редирект этого пользователя на нужную страницу в нашем случае это smash аккаунт, а так как эта страница является защищённой, то есть приватной, то при доступе к ней спринг секьюрити запу.
324: Соответствующую проверку, он смотрит, какими ролями нужно обладать, чтобы эту страницу открыть в security конфиге. Мы указали, что страница слэш аккаунт доступна с ролями юзер или админ, потом spring security достаёт объект аутентификейт для.
325: Текущего пользователя и проверяет, какие у него по факту есть Роли, которые мы только что назначили при процедуре авторизации, и если у пользователя действительно есть подходящие Роли, например, юзер, то spring security понимает, что данному пользователю данный приватный ресурс досту.
326: Поэтому он пускает этого пользователя на этот ресурс и отображает нужную веб страницу. Вот как-то так все это и работает очень круто если по итогу у вас получилось разобраться в какой последовательности и что и как под капотом работает, потому что большинство джуниор
327: Разработчиков они понятия не имеют, как это работает под капотом. Они просто знают, что им нужно предоставить. User details сервис, который из бд вернёт нужного пользователя и все магическим образом начинает работать. Но как и почему это работает, они, конечно же, не понимают. В рамках данной лекции. Я
328: Также предлагаю немножко доработать наше веб приложение, например, на странице Логина отображать текст с ошибкой. Если пользователь ввёл неправильные креды, например, пароль. Смотрите, как это работает сейчас, если я введу правильный логин, то есть тест собака джимэйл точка.
329: И теперь я введу неправильный пароль, например 1 2 3 я выполняю логин, то у меня просто обновилась страница, обратите внимание на url, у меня теперь отображается вопрос и err это значит, что в процессе Логина произошла какая-то ошибка, но тем не менее.
330: На самой странице мы ничего не отображаем, поэтому пользователю не очень понятно, что произошло. Я предлагаю этот момент доработать для этого в паблик авторизейшн контроллере в методе get логин пейдж я предлагаю добавить дополнительную логику.
331: Давайте объявим.
332: На самой странице мы ничего не отображаем, поэтому пользователю не очень понятно, что произошло. Я предлагаю этот момент доработать для этого в паблик авторизейшн контроллере в методе get логин пейдж я предлагаю добавить дополнительную логику. Давайте объявим
333: Здесь модель.
334: Импортируем нужный класс и теперь давайте свяжем аргумент этого метода с квери параметром эрр, который как раз-таки и добавляется в url к логину. Если произошла какая-то ошибка поэтому указываем реквест парам тип данных аргумента это стринг и
335: Название аргумента это который целиком и полностью совпадает с самим квери, параметром, который добавляется к этому адресу. Слэш, логин в случае ошибки, но данный параметр он является необязательным. То есть мы можем просто перейти на страницу слэш логин, не указывая никакой error, поэтому
336: Error.
337: Название аргумента это error, который целиком и полностью совпадает с самим квери, параметром, который добавляется к этому адресу. Слэш, логин в случае ошибки, но данный параметр он является необязательным. То есть мы можем просто перейти на страницу слэш логин, не указывая никакой error, поэтому
338: Здесь нам также нужно дополнительно написать, что он у нас реквайрд фолс, то есть не обязателен. И теперь давайте добавим соответствующую проверку. Если у нас этот error, он не null, то есть у нас действительно в нашем урле присутствует такой параметр, то для нас
339: Это обозначает, что произошла какая-то ошибка и нам на нашей веб странице нужно вывести какое-то дополнительное вспомогательное сообщение об ошибке. Поэтому мы в нашу модель добавляем атрибут, который назовём, к примеру, следующим образом из
340: Кейшн фейлд тру
341: И в качестве значения этого атрибута передадим. Это значит, что у нас аутентификация провалилась. Теперь переходим на саму страницу Логина. У нас здесь есть закомментированная часть разметки, которая как раз-таки и отвечает.
342: Кейшн фейлд и в качестве значения этого атрибута передадим тру. Это значит, что у нас аутентификация провалилась. Теперь переходим на саму страницу Логина. У нас здесь есть закомментированная часть разметки, которая как раз-таки и отвечает
343: За то, чтобы отобразить это вспомогательное сообщение о том, что мы ввели либо неверный имейл или пароль. Но данный дифф мы хотим отображать только в том случае, если действительно произошла какая-то ошибка, а она произошла, если в нашей модели присутствует наш флаг, который мы передали.
344: Из аутентике шен фейлд, для того, чтобы воспользоваться специальными атрибутами тайм лив, нам нужно добавить в наш тег html соответствующее пространство, поэтому давайте перейдём на account page, скопируем данные пространства, возвращаемся на логин.
345: И добавляем его вот сюда теперь для данного Тега мы можем написать условие t. H if знак доллара, фигурные скобки и пишем само условие мы обращаемся к модели данных из аутентике н. Фейлд, то есть, если у нас этот флажок заполнен.
346: И имеет значение true, то тогда мы отобразим данный дифф, чтобы убедиться, что все работает верно, давайте перезапустим наше веб приложение и на странице Логина попытаемся указать, к примеру, неверный пароль.
347: Итак, приложение запустилось. Переходим в браузер. Давайте попытаемся обновить страницу, где есть данный квери параметр error и у нас действительно отображается это сообщение о том, что мы предоставили либо неверный емейл, либо пароль, если просто открыть страницу слэш, логин.
348: То у нас отображается самая обычная форма без каких-либо вспомогательных сообщений, но если мы попытаемся ввести какие-то неправильные данные, например пароль 1 2 3 кликаем логин нас перебрасывает на страницу логин, вопрос hr и в этом случае также
349: Отображается дополнительная информация об ошибке, о том, что мы ввели неправильно либо имейл, либо пароль. В нашем случае это пароль. Таким образом мы сделали нашу логин страницу гораздо более юзер френдли, потому что теперь у пользователя хотя бы будет предположение о том, что именно он сделал
350: Неправильно. 2 вещь, которую я бы хотел доработать в этом web приложении, это сделать. Правильную процедуру регистрации. На данный момент после регистрации мы делаем редирект на страницу Логина и заставляем пользователя ввести свои креды. Только после этого. Пользователь
351: Сможет войти в систему и пользоваться различными приватными ресурсами. Но, согласитесь, это не очень хороший подход. Никакие сайты так не работают. После регистрации совсем нет нужды проходить процедуру идентификации, аутентификации и авторизации, потому что поль
352: Пользователь только что создал аккаунт, указал там оригинальный пароль. И по идее, мы должны верить ему по умолчанию. Именно так большинство сайтов и работает. Если вы только что зарегистрировались и создали аккаунт, то вас сразу же логинит в систему и вы можете пользоваться любыми прива.
353: Платными ресурсами. Поэтому я предлагаю реализовать такую штуку, которая называется автологин. То есть мы будем автоматически логинить пользователя сразу же после для того, чтобы не вводить креды ещё раз на странице Логина. Для этого в паблик авторизейшен
354: Регистрации.
355: Платными ресурсами. Поэтому я предлагаю реализовать такую штуку, которая называется автологин. То есть мы будем автоматически логинить пользователя сразу же после регистрации для того, чтобы не вводить креды ещё раз на странице Логина. Для этого в паблик авторизейшен
356: Контроллере. Нам нужно реализовать ещё 1 дополнительный метод, который как раз-таки и будет выполнять автологин. Определим новый метод. Он у нас будет приватный, значит доступен только в рамках этого контроллера никто снаружи пользоваться им не сможет. Возвращаемый тип у него будет
357: Void и назовём мы данный метод форс автологин, что в переводе на русский обозначает принудительно выполнить автологин, в качестве аргументов мы будем принимать имейл пользователя, а также пароль.
358: Пользователя капотом.
359: Помните, когда совсем недавно я схематично, в презентации объяснял, как работает процесс Логина, то на процедуре авторизации я рассказывал, что spring security под создаёт специальный объект аутентике н. В. Который передаёт набор.
360: Пользователя помните, когда совсем недавно я схематично, в презентации объяснял, как работает процесс Логина, то на процедуре авторизации я рассказывал, что spring security под капотом создаёт специальный объект аутентике н. В. Который передаёт набор.
361: Ролей, которые свойственны данному пользователю. Именно поэтому теперь пользователь может считаться залогиненным в систему и получать доступ к приватным ресурсам. Так вот, когда мы говорим про автологин, то, по сути, нам нужно выполнить Ровно то, что делает спринг секьюрити на этапе авторизации.
362: Только сделать это. Делается это следующим образом. Нам нужно здесь перечислить набор ролей, которые свойственны для данного пользователя. Поэтому пишем, используем уже знакомый нам тип данных гренте. Афорить
363: Вручную сет это simple называем.
364: Только сделать это вручную. Делается это следующим образом. Нам нужно здесь перечислить набор ролей, которые свойственны для данного пользователя поэтому пишем сет, используем уже знакомый нам тип данных. Это simple гренте афорить называем.
365: Данную переменную, как rose импортируем, сет пишем, равно и нам нужно перечислить здесь те Роли, с которыми данный пользователь будет автоматически залогинен в систему, так как при регистрации у нас создаются пользователи именно с ролью юзер, то именно её
366: Мы как раз-таки и можем здесь присвоить пользователю при автологин, поэтому пишем коллекшнс, синглтон, обращаемся к енаму, юзер, ролл, выбираем юзер и сразу же преобразовываем её к авторити для того, чтобы она подходила для
367: Данной коллекции точка с запятой. Итак, набор ролей готов. Теперь нам нужно вручную создать объект типа аутентике шн, что мы и делаем аутентике шн.
368: Равно нью аутентике шен это просто интерфейс, но нам нужно предоставить здесь какую-то реальную реализацию. И такая реализация действительно есть. Это user name песпорт, аутентике шен токен, именно этот класс и выбираем.
369: Он в качестве аргументов требует у нас принципл. Это и есть логин нашего пользователя, то есть имейл, потом креденшлс. В данном случае это пароль пользователя и афорис, то есть набор ролей, которые свойственны данному пользователю. Мы передаём туда нашу
370: Лекцию с ролями, внутри которой находится всего лишь 1 роль, это user. Теперь, после того, как сам объект аутентике шен создан, нам нужно присвоить этот объект текущему пользователю, который вот прямо сейчас выполняет данный запрос к серверу, который прямо сейчас регистри,
371: Делается это при помощи такого специального класса, который нам предоставляет спринг секьюрити и называется security context холдер мы обращаемся к этому классу, у него есть статик метод get context, который возвращает контекст.
372: Для текущего запроса к нашему серверу, то есть вызов данного метода get context, он будет возвращать нам разные объекты в зависимости от того, какой именно пользователь сейчас сделал запрос вот по Такому адресу. Слэш, регистрейшн, потому что
373: Вызов этого get контекста, он привязан к http запросу, который прямо сейчас выполняется на нашем сервере. То есть в рамках которого происходит вызов данного кода. Это значит, что вызвав такой метод, мы получили доступ к контексту для того пользователя, для которого
374: Мы сейчас выполняем процедуру регистрации, и поэтому именно для этого пользователя мы вызываем сет аутентике н и передаём туда объект, который только что создали все это. Весь набор этих действий делает за нас под капотом спринг секьюрити на
375: Этапе, который называется авторизация, когда мы выполняем логин, здесь же мы все это сделали вручную, то есть выполнили автологин. Последнее, что нам осталось сделать, это вызвать данный метод. После того, как мы создали новый аккаунт пользователя, здесь мы вызываем
376: Форс автологин передаём туда имейл этого пользователя, а также хэш пароля. Это значит, что прямо во время мало того, что мы создали нового пользователя и положили эту запись в бд, мы тут же выполнили.
377: Регистрации.
378: Форс автологин передаём туда имейл этого пользователя, а также хэш пароля. Это значит, что прямо во время регистрации мало того, что мы создали нового пользователя и положили эту запись в бд, мы тут же выполнили
379: Автологин. Это значит, что уже теперь, после выполнения данного метода, пользователь обладает нужными ролями и теперь может получать доступ к защищённым ресурсам, которые ему доступны. Значит, нам не нужно делать редирект на страницу Логина, потому что логин теперь нам вообще не
380: Нужен после регистрации. Для этого сразу делаем редирект на страницу аккаунт для того, чтобы сразу же после регистрации пользователь мог видеть список дел. Давайте теперь убедимся в том, что это все действительно работает. Перезапустим наше веб приложение и попытаемся сейчас создать ещё 1
381: Нового пользователя.
382: Итак, вот у нас здесь страница Логина. Давайте перейдём на Сайнап, то есть на регистрацию и создадим ещё 1 пользователя. Это у нас будет тест название пользователя, допустим, вот, точнее, имейл пользователя тест 7 7 7, собака джимейл.
383: Точка ком и пароль. Также введём цифры от 1 до 8. 1, 2, 3, 4, 5, 6, 7, 8. Кликаем. Сайнап. Обратите внимание, что произошла регистрация. Нас сразу же перебросило на smash аккаунт. Это значит, что автологин действительно сработал. И теперь страница слэш аккаунт, она действи
384: Действительно открылась для данного пользователя. Если мы посмотрим бд, то мы увидим, что данный пользователь действительно появился. Емейл тест 7, 7, 7, собака джимейл, вот с таким вот паролем роль у него также user. А значит, что все работает, с чем я вас и поздравляю, потому
385: Что благодаря этому наше веб приложение стало ещё на шаг ближе к реальным веб приложениям, которыми пользуются абсолютно все люди в повседневной жизни. А теперь давайте подведём итоги для данной лекции. Во первых, мы с вами разобрались с требованиями к форме Логина.
386: Потому что когда мы говорим про процесс регистрации, то этот процесс целиком и полностью ложится на плечи разработчиков. Мы должны контролировать весь этот процесс от и до, и сами должны его запрограммировать, в то время как процесс Логина он достаточно сложный. Именно поэтому всю эту реализацию берет.
387: На себя спринг секьюрити он предоставляет уже готовый обработчик для таких запросов, по которым выполняется процесс Логина. Наша же задача сводится к тому, чтобы на веб странице Логина предоставить правильную форму, при сабмите которой будет отправлен, ну,
388: Запрос на нужный адрес, который спринг секьюрити ожидает, в частности, все такие формы они всегда должны отправлять именно post http запросы. Во вторых, запрос должен отправляться на url smash логин, но этот урл он является урлом по умолчанию для spring.
389: При конфигурации безопасности нашего приложения данный url мы можем переопределить, то есть указать любой подходящий нам. И также данная форма обязательно должна содержать 2 квери параметра. Это username и песвот, потому что именно эти квери пара
390: Spring security ожидает на стороне обработчика для того, чтобы запустить процесс Логина наименование для 2 этих квери, параметров также можно изменить при настройке безопасности приложения, что мы на практике, кстати, и делали, потому что для юзернейма мы переопределили название.
391: Параметра. Он у нас называется имейл, поэтому и на веб странице внутри формы данный импут у нас также носит название имейл. В общем, выполнив все эти требования при сабмите такой формы, специальный обработчик спринг секьюрити словит этот запрос и запустит процесс логи.
392: Сам процесс Логина глобально состоит из 3 этапов. 1 это идентификация, 2 это аутентификация и 3 это авторизация. Давайте теперь пару слов расскажу про каждый из этих этапов. Процедура идентификации подразумевает, что по идентификатор
393: Предоставленному пользователем. В нашем случае это имейл. Мы должны каким-то образом идентифицировать данного пользователя, то есть понять, есть ли такой пользователь в нашей системе. И если есть, то предоставить дополнительный набор данных про этого пользователя. Процедура
394: Аутентификации это проверка подлинности, когда сравнивается эталонный пароль, который лежит в бд для данного пользователя, с тем фактическим паролем, который предоставил пользователь на странице Логина. И если эти 2 пароля совпадают, то значит, что
395: Процесс аутентификации успешно пройдён. Система будет верить Такому пользователю, потому что он предоставил правильный пароль. 3 процедура. Авторизация это назначение Нужных ролей для данного пользователя, для того, чтобы после Логина у него был доступ к приватным.
396: Ресурсам, к которым он может получить доступ в соответствии с этими ролями, когда мы говорим про spring security, то 2 и 3 этап, то есть аутентификацию и авторизацию, спринг секьюрити берет на себя целиком и полностью, в то время как процедуру идентификации он возлага.
397: На нас как на разработчиков данного веб приложения, потому что spring security ничего не знает об источнике данных, то есть где именно находятся все наши пользователи, спринг секьюрити самостоятельно не может идентифицировать пользователей, именно поэтому за это отвечаем мы.
398: Разработчики мы можем запрограммировать там абсолютно любую логику, но конкретно в нашем случае мы обращались к бд и действительно пытались найти там пользователя по, и если мы такого пользователя находили, то для того, чтобы процессинг Логина действительно
399: Его имейлу.
400: Разработчики мы можем запрограммировать там абсолютно любую логику, но конкретно в нашем случае мы обращались к бд и действительно пытались найти там пользователя по его имейлу. И если мы такого пользователя находили, то для того, чтобы процессинг Логина действительно
401: Работал. Мы предоставляли дополнительную информацию об этом пользователе. Это его эталонный пароль, который будет использоваться на процедуре аутентификации, а также набор ролей, которые данному пользователю нужно назначить на процедуре авторизации. Если проверка паролей пройдёт
402: Успешно. Ну и если все эти 3 этапа успешно пройдены, то значит, что наш пользователь успешно залогинен в систему, ну и вишенка на торте. Мы попытались разобрать весь этот схематично, прямо в презентации, ещё раз дублировать все это здесь я не вижу смысла при желании
403: Процесс.
404: Успешно. Ну и если все эти 3 этапа успешно пройдены, то значит, что наш пользователь успешно залогинен в систему, ну и вишенка на торте. Мы попытались разобрать весь этот процесс схематично, прямо в презентации. Ещё раз дублировать все это здесь я не вижу смысла при желании
405: Можно пересмотреть данный фрагмент этой. Ну а на этом, в принципе, все. Я благодарю всех вас за внимание. Конечно же, не забывайте про выполнение всех домашних заданий, а я с вами прощаюсь. До встречи.
406: Лекции. Ну.
407: Можно пересмотреть данный фрагмент этой лекции. Ну а на этом, в принципе, все. Я благодарю всех вас за внимание. Конечно же, не забывайте про выполнение всех домашних заданий. Ну а я с вами прощаюсь. До встречи.