Создание Spring Security REST API с использованием JWT токена
HTML-код
- Опубликовано: 8 апр 2019
- Ссылка на репозиторий с исходным кодом проекта:
github.com/proselytear/jwtapp...
Ссылка на документацию Spring Security:
docs.spring.io/spring-securit...
CSRF:
ru.wikipedia.org/wiki/%D0%9C%...
habr.com/ru/post/318748/
В данном видео создано REST API с использованием Spring Security. Аутентификация и авторизация реализованы с использованием JWT токена.
Технологии:
Java, Spring (IoC, Web, Data, Security), MySQL, Lombok, JsonWebToken, Liquibase, Git.
Прелесть данного туториала в том, что он не слишком сложный и не слишком простой.
То есть, это не банальный 'hello world', который не понятно как применять в реальном проекте.
Также это не перегруженный проект в котором сложно разобраться.
Золотая середина!
Очень классно рассказал о Spring Security. Какие компоненты за что отвечают. Наконец-то стало ясно как оно работает и как настраивать.
П.с. Надеюсь ты уже улучшил свои скилы работы с Optional.
Очень крутое видео! Спасибо. Единственное полное видео по этой теме, которое смог найти.
Очень полезное видео! Спасибо! Еще и тему DTO зацепил - вообще Красавчик!
Спасибо за отзыв!
А еще и показал как правильно аннотировать BaseEntity !
Большущее тебе спасибо, бро! Доходчиво, понятно, супер. Очень сильно жизнь облегчило, как раз пишу дипломный по курсах...
Все работает, спасибо больше за видео. Было бы круто добавить походу больше пояснений про внутреннее устройство spring security и почему сделано так а не иначе вместо надиктовывания строчек кода.
Спасибо за отзыв!
По поводу более глубокого объяснения - здесь мне будет крайне сложно превзойти документацию, изучение которой я крайне рекомендую.
docs.spring.io/spring-security/site/docs/current/reference/html5/
Цель видео - дать самое базовое представление и практический навык работы с технологией.
Спасибо за видео. Не пропадайте, очень интересно!
Спасибо за отзыв, Александр. Постараюсь )
@@EugeneSuleimanov Евгений, снимите туториал по микросервисам)
Спасибо большое за объяснение столь важной темы)
Очень классное виде! Очень жаль, что таких больше не выпускаете
Все отлично, есть несколько пожеланий:
1. Autowired над конструктором можно не вешать, т.к. других конструкторов нет и при создании бина Spring сам поймет что инжектить.
2. Аннотация @AllArgsConstructor, как уже писали - сильно поможет.
3. В имплементации UserDetails сильно нужны @AllArgsConstructor и @Data, т.к. отвлекает генерация геттеров\сеттеров.
4. Публичный конструктор без параметров в фабрике не нужен, javac сам подсунет если не найдет.
5. Было бы неплохо добавить вариант ограничения доступа через аннотации, типа @RolesAllowed/@Secured
Спасибо, не пропадайте больше!)
Спасибоза отзыв. Постараюсь )
Евгений, у вас лучшие ролики, доходчиво и без воды, жаль что видео приходится ждать месяцами :(
Также мне очень хотелось бы увидеть продолжение данного ролика с использованием mapstruct
Спасибо за отзыв, Андрей. Постараюсь выложить вторую часть в течение нескольких недель (обновление токена, регистрация и т.д.)
@@EugeneSuleimanov Это хорошие новости, будем ждать, спасибо большое
Подскажите, почему не используете DI для JwtTokenFilter и JwtTokenProvider, а создаете их вручную? Можно ли так же аннотировать эти классы через @Component и заменить все new на инжект через DI?
Спасибо вам большое за ваш труд. Лучшей материал на RUclips по этой теме СУПЕР.
Спасибо за отзыв!
Отлично объясняешь, видео очень помогло, большое человеческое тебе, друг)
Спасибо за отзыв! Рад, что материал оказался полезен.
Спасибо большое! Не смотря на длительность было очень интересно смотреть)
Спасибо за отзыв :)
@
Eugene Suleimanov Огромное спасибо за данный урок! Подскажите каким образом можно токен сделать недействительным, выполнив logout. Как я понял можно создать сущность "чёрный список" для JWT токенов, но как правильно реализовать до меня не доходит. Или для этого и существует Auth 2.0 и работа с ним? Накиньте пожалуйста мыслей!
Не мог не отписать. Очень грамотно сделано и подано. Спасибо.
Спасибо за отзыв!
Спасибо большое за видеоурок. Он мне очень помог. Не пропадайте ;)
Спасибо за отзыв! Постараюсь)
Превосходное видео и объяснения. Было бы здорово для полноты катрины добавить регистрацию пользователя в этом же проекте. Если есть такое видео, то поделитесь пожалуйста ссылкой
Спасибо за урок мне очень понравилось
Спасибо за отзыв!
спасибо вам, очень круто
Не слишком сложно и не слишком легко. То, что нужно!
Спасибо за отзыв!
спасибо за шикарный видос) даже код есть, мечта))) чуть бы код покрупнее.
Здравствуйте ) А как интегрировать liquibase в Spring MVC, чтобы при запуске приложения создавались таблицы в БД? Я пытаюсь сконфигурировать плагин со всеми настройками и там указать путь к файлу changelog.xml. Но таблицы не создаются.
Спасибо , как всегда круто)
Респект, подача материала просто супер! Единственное замечание, если можно код покрупнее, а так все очень доходчиво.
Спасибо за отзыв и замечание, постараюсь исправить в будущем.
Спасибо за Урок, лучшая объяснения)) Вопрос, можешь снимать урок где добавляешь возможность logout и remember me???)
Нашел хорошее видео на ту же тематику, но уши кровоточат от чудовищного каверканья английских терминов. Как же приятно слушать Евгения
Спасибо за отзыв!
Спасибо большое за видео! Подскажите, пожалуйста, а если у нас LDAP авторизация, подход остается тот же?
С возвращением!)
Спасибо)
Отличный выпуск) спасибо за ваш труд)
Спасибо за отзыв!
Спасибо за отзыв!
Спасибо большое!
Шикарный видос!
Евгений, спасибо за видео урок. Как можно реализовать refresh token на базе этого rest api?? буду очень благодарен
Похоже ответа не будет(
Евгений спасибо большое за ваши видео. В них всегда можно чему то научиться. Такой вопрос: у вас есть опыт работы с чем то реактивным spring web flux или просто rxjava? Было бы супер увидеть от вас видео на такую тему.
Спасибо за отзыв, Alex.Да, конечно. Я подумаю, что можно сделать на эту тему.
Все хорошо, конечно, слов нет, большое спасибо! Но было бы совсем замечательно, если бы Евгений каждый момент, который он называет "ну, тут все понятно", хотя бы в двух словах пояснял. Потому что, если я пришел смотреть такое длинное видео, значит я просто не знаю, как в принципе реализовать Security на Spring с JWT. Приходится гуглить все не пояснённые моменты типа что такое grantedauthority и simplegrantedauthority и еще несколько вещей. А тем кому все эти моменты понятны, он точно не будет тратить 1,5 часа на видео. Я ничего против сказать не хочу, абсолютно весь материл Евгения просто бестселлер, браво! Поэтому когда я искал в youtube как реализовать Spring Security with JWT и увидел Евгения, с радостью начал смотреть, так как уже знаком с высоким профессионализмом этого замечательного человека и программиста, а данный комментарий -- просто рекомендация.
Спасибо за отзыв, Сергей! На канале есть более подробное видео по основам Spring Security:
ruclips.net/video/7uxROJ1nduk/видео.html
Надеюсь, оно будет более полезно. И спасибо за рекомендацию.
@@EugeneSuleimanov Огромное спасибо, завтра займусь изучением!
Субъективно, Flyway по удобней будет для миграции, и понятный sql, а не xml.
Евгений, спасибо за урок!
Вопрос: если мы маппим юзеров и роли через @ManyToMany, то в итоге получаем три таблички (users, roles, users_roles), однако, если мы сделаем @ManyToOne, то у нас будет только две таблицы (users, user_role(Id, user_id, role) и нужно указать уникальную связку user_id+role).
Есть ли между этими подходами принципиальная разница и, если есть, то какой лучше?
В данном случае - нет, но, тогда мы не сможем присвоить юзеру несколько ролей. Это, не критично, потому что мы можем дать каждой роли определённые права (добавить коллекцию пермишенов, например).
Сказать, какой лучше сложно, но, я бы использовать @ManyToOne в реальной жизни.
При отсутствии в заголовке токена необходимо возвращать 401 Unauthorized, а не 403 Forbidden. В данной имплементации, к сожалению, всегда 403.
Спасибо большое! Сделайте, пожалуйста, курс по микросервисам, докеру)
Это соль на рану. Уже крайне давно хочу записать серию подобных видео, но не хватает времени, к сожалению... ((
Крайне надеюсь, что в этом году получится. Спасибо.
@@EugeneSuleimanov Удачи!
Очень круто. Ты красава!!!!
Спасибо за отзыв!
Добрый день! Как отправить POST запрос для создания нового пользователя и сохранения его в базе, если еще никакой пользователь не авторизован?
Спасибо за отличный урок!
Просьба разъяснить насколько это хороший тон или насколько это актуальный подход, что при каждом REST запросе идет обращение в базу для получения данных пользователя. Разве не требуется поместить эти данные в claims?
Спасибо!
Рекомендую вам в дальнейшем использовать Lombok, удобная тула для того чтобы избавиться от явной прописи конструкторов геттеров и сеттеров (если вкратце)
Евгений, спасибо огромное за Ваш труд! Спустя годы контент все равно остается полезным и актуальным!
Проясните пожалуйста несколько вопросов по видео:
1) 38:58 А зачем все-таки этому классу пустой конструктор по умолчанию? И можно здесь же пояснить зачем именно сделали класс final (т.е. в чем будет проблема если он будет не final)?
2) 42:15 почему User.roles нужно копировать в new ArrayList перед конвертацией в GrantedAuthorities (строка 26)?
3) 57:12 Зачем переопределять метод authenticationManagerBean ничего не меняя по сути в имплементации, а только вызывая super (т.е. он и без этого будет создан спрингом и вести будет себя точно так же)?
Привет.
1) Видео сделано давно , есть неточности и чтобы их поправить , придется повозиться.
2) По пункту 1, 2 согласен.
3) Возможно, при создании своей аутентификации , ты обязан явно внедрить бин
AuthenticationManager в AuthenticationRestControllerV1, поэтому в конфигурационном классе его как раз и создаешь (без всяких super. и само собой не переопределяя , хотя раньше нужно было).
* В целом крутой материал , как всегда - спасибо)
Прошло уже какое-то время, но могу ответить на второй пункт. Копирование делается на тот случай, если мы роли храним не в List, а в Set. Недавно столкнулся с этим пока практиковался и теперь запомню на долго)
@@lehatalant9878 поясни плиз в чем именно может быть проблема даже если где-то Set будет?
@@petrovandrey9735, Spring Security работает только с List и если мы вставим Set, тогда появится ошибка.
Понял, спасибо!
спасибо!
Круто.
zdrastvuy uvajaemi Eugene , spasibo bolshoe chto delishsya svoim opitom i znaniem s nami) prosto malenkaya prosba k tebe, font size nemnojko uvelichivay
Большое спасибо!
Спасибо за отзыв!
"toor" Молодец Женя😁
Спасибо
Спасибо за урок! Когда истекает срок jwt token-а spring возвращает html страницу, а надо ведь json, пробовал ControllerAdvice, результата нет, пока ищу ответ. Как можно это решить?
very good tutorial!
Спасибо за отзыв, Сергей.
Как это все сделать с решрештокеном?
32:35 Хорошо)
мой перфекционист в душе: ну что же тут хорошего, где передаваемый параметр? 😁
А как можно совместить авторизацию с вводом пароля и логина + csrf токен(стандартную для спринг секьюрити) и jwt для подальшего использования (после авторизации) при отправке запросов на сервер? Подскажите.
Четко!
Лайк ещё до просмотра)
Спасибо :)
Добрый день! Проясните, пожалуйста, такой момент.
В методе контроллера login вызывается
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, requestDto.getPassword()));
При этом, насколько я понял, используется дефолтный AuthenticationManagerDelegator в качестве реализации.
Если так, то в каким образом он понимает, как валидировать пароль при логине? То есть как связаны конкретно ваша таблица с паролями и сущность authenticationManager?
Добрый день. Отличная работа, очень благодарен. Но возникает один вопрос. Как данный сервис использовать между всеми докеризированными микросервисами? Не создавать же отдельный jwt server для каждого. Должно быть решение.
А почему классам User и Role нельзя сразу имплементировать интерфейсы UserDetails и GrantedAuthority соответственно?
Здравствуйте, очень хочется узнать Ваше мнение по поводу построение большого REST приложения по правилам хорошего тона.
Есть ли смысл и правильно ли использовать использовать entitiy класы и для бизнес логики и для представления, или же последнее заменять так званными проекциями в spring фреймворке? Как я понимаю entity классы отвечают за представление таблицы базы данных, и использовать эти классы в качестве представление не есть хорошо. Хотелось бы узнать это от более опытного разработчика.
Добрый день, Александр. Если делаем с нуля, то я бы использовал DTO или graphQL. Есть некоторые ситуации, когда передача самих объектов может подвести. Это, если в общих чертах.
@@EugeneSuleimanov Спасибо за ответ!
@Eugene Suleimanov: Благодаря Вашим видео учусь писать правильно код. Спасибо за это огромное. Вопрос: В чем смысл аннотации @Table @Column если имя совпадает с названием таблицы/столбца ?
Это не обязательно, но, обычно, именуют, просто как договоренность. Это на основании моего опыта. Спасибо за отзыв!
Спасибо за видео, очень наглядно и полезно. Возник такой вопрос: как можно перехватить JwtAuthenticationException, чтоб на условный фронт возвращался не код 500, а можно было вернуть 401 или 403?
Спасибо за отзыв!
Через глобальный обработчик ошибок.
1:10:15 При вводе неправильного пароля "throw new BadCredentialsException("Invalid username or password");" кажется не сработал? Не вижу этого сообщения в json response.
@50:14 Очень понравился материал. Однако, не разумнее затолкать инициализацию бина passwordEncoder в корень конфигурации проекта, а не в отдельном (пусть и магистральном) компоненте JwtTokenProvider?
У меня вообще ошибка выпадает, что не может найти такой бин
Спасибо за видео!
Делаю по вашему примеру и возникла проблема: при отправке невалидного токена JwtAuthenticationException возвращает HTML вместо JSON. AuthenticationEntryPoint перехватывает эту ошибку, только в случае пустого токена, при каких либо данных в токене возвращается HTML.
Подскажите, как это можно обработать, а то уже который день над этим бьюсь) Заранее спасибо :)
Разобрались?) Я тоже на этом застрял))
Евгений спасибо большое за видео. На текущий момент это единственное видео, которое мне помогло добавить авторизацию с jwt. У меня есть небольшой пет проект с Spring Boot и Angular, где я успешно внедрил данную технологию, но так же у меня остались вопросы в частности о том как создавать refresh токен и как с ним работать. Но больше всего мне интересно как работать с Oauth2 и как совместить его с jwt. Как бы я не старался, у меня не получается совместить их вместе из-за очевидной нехватки знаний и опыта в этих технологиях. Как сделать так, что при запросе с сервера Angular по REST пришел запрос на сервер Spring и Spring обратился к внешнему серверу(Facebook, Google etc, на которых у меня заранее установлено приложение и известны все данные в виде секретного ключа и так далее) и получил от них ответ в виде данных пользователя, который потом передаст по REST другому серверу(Angular). Такая же схема работы с jwt и по сути они отличаются только тем, что от внешнего сервера(Angular) в случае авторизации через Oauth2 запрос приходит с пустым телом(т.к. нет ни пароля ни логина, они вводятся на стороннем 3м сервере). В конченом итоге я хочу реализовать авторизацию пользователя на выбор: или через внутреннюю самого сайта, или через внешнюю(Facebook, Google etc). Все эти сведения только лишь теоретические. Как это реализовать? Куда смотреть-хотя бы на каких ресурсах внятно это объясняется или я не так понимаю, ибо чем больше я ищу информации про REST авторизацию с Oauth2, тем больше у меня возникает вопросов. В идеале хотелось бы увидеть Ваше видеоруководство на подобии текущего, где будет освещенная данная проблема, т.к. я считаю данный вопрос не является каким то частным случаем, на каждом современном веб-ресурсе присутствует авторизация двумя вышеперечисленными способами. Даже на украинском гос.сайте по оплате ЖКХ услуг есть авторизация через гитхаб.
Спасибо за ваш отзыв!
Что касается OAuth, то мне кажется, здесь важно понять сам принцип этого подхода (кто именно проверяет безопасность в данном случае).
Пока в планах нет выкладывать видео по данной теме, но, мне кажется, что уже есть готовые примеры
100% уже неактуально для автора вопроса, но для ищущих информацию может быть полезно. Шестое издание "Spring в действии" помогает в реализации по данной тематике. Глава 5.3.3.
Еще хотелось бы узнать ответ на такие вопросы:
В BaseEntity.java класс должен быть abstract ? (У вас просто public class BaseEntity)
Не обязательно, но можем сделать и абстрактным. Здесь нет методов, которые были бы нам нужны абстрактными, только общие поля. Поэтому - обычный класс
Что-бы юзеру фабрику не городить можно в userDetailIml просто положить полем appUser и с него уже выдать все поля геттерами
Евгений, уроки отличные. Но надо сделать хороший звук (здесь он глухой и не заднем плане где-то) и картинку с кодом крупнее.
Спасибо, да,есть проблем, стараюсь исправить в новых видео.
@@EugeneSuleimanov где можно вам задать вопросы по этому проекту? На первом же запуске, когда ещё БД пустая, выдаёт ошибку. Дальше писать не рабочее приложение не интересно. Есть какой-нибудь оперативный вариант связи с вами?
Подскажите пожалуйста, столкнулся с проблемой, делал реализацию jwt в спринге по полному подобию, всегда получаю 403 статус, то есть токен я получил, запихнул в headers, но получаю Access.DENIED. просто написал тоже на спринг бут и все работает, может для простого спринга нужны какие нибудь дополнительные конфиги? Буду благодарен за любой совет
Привет, тоже только что запарился с этим. Весь прикол в том, что в станлартном виде мы отсылаем "Bearer " + наш токен, а автор видео отсылает "Bearer_" + наш токен. Потому, когда ресолвится токен, система его не воспринимает
@@shunic да это самое первое что поменял) я перелопатил все) уже пятый день дебажу, лезу вглубь, чтобы выяснить из за voterы голосуют за отказ
Евгений спасибо за ролик по нём написал свой первый jwt для своего проекта. Но мне не совсем ясно зачем админу давали роль и админа и юзера ? Для ендпоинта админа дали роль админа для всех остальных запросов у нас authenticated же есть.
Спасибо за отзыв!
Даётся набор ролей для гибкости, так как здесь не используются пермишены. В нормальной практике - будет одна роль с набором доступов.
@@EugeneSuleimanov но если бы мы админу не дали права USER он бы смог всё равно пользоваться всеми запросами согласно нашей конфигурации. Верно ?
Добрый день, Евгений, все больше углубляюсь в понимание Spring Security, и почитав много документации и разобрав Ваш пример, у меня возник вопрос:
Исхожу из посыла, что токен придуман для общения между серверами, чем между пользователями и сервером, чтобы постоянно не брать аутентификацию из сесии ,а там из контекста. и как я понял фронт может обойтись без файлов куки.
Тем самым токен позволяет не использовать сессии и как я понял использовать аутентификацию только 1 раз если у пользователя нету токена, чтобы его выдать, а в дальнейшем только проверять токен и тем самым ускорять работу.
Само собой, если кто-то украдет токен, и без лишней проверки на аутентификацию, то будет серверу плохо.
Но все же,
1. Вопрос.
Почему в классе JwtTokenFilter в методе doFilter вы проверяете токен , и если с токеном все хорошо, вы создаете аутентификацию, опять проверяя существует ли юзер в базе данных? но прибегая к обычному UserDetails , если вы используете до этого JwtUser который имплементирует userdetails.Возможно в JwtTokenProvider должен был инжектиться не UserDetailsService, а JwtUserDetailsService?
2. Вопрос
Вместо проверки Аутентификации в сесии, мы в том же методете ее устанавливаем каждый раз после проверки токена. Зачем мы это делаем если с токеном все впорядке? почему мы не может пропустить данный пункт(если это еще один пособ проверки, то вопрос исчерпан), и там же мы проводим проверку на null, как аутентификация может быть null, если валидный токен к нам пришел ?
3. Вопрос
В контольлере , /login Вы проводите аутентификацию с помощью AuthenficationManager, и если она проходит, то соответственно Вы выдаете токен. Насколько я понял аутентификация происходит автоматически, в остальных методах вы проверку не проводите в ручную, а так же вы не проводите проверку токена, это мне тоже совсем не понятно. Я понял что вы добавили новый фильтр перед аентентификацией, но как его пройти, если токена нету ?
Фильтр первый увидел токена нету, включает следующий UsernamePasswordAuthenticationFilter ?
Меня не покидает ощущение что нужно было заоверайдить AuthMeneger на новый провайдер, который связан с JwtTokenProvider и JwtUserDetailsService, или нельзя базовую аентентификацию переписывать на JWTToken? поясните этот момент, пожалуйста.
Извините, если плохо изложил свои мысли, но данные моменты не дают покоя моей голове, если я что-то не правильно понял о процессе security, разъясните пожалуйста, или дайте ссылку на понимания данного момента.
Спасибо за комментарий!
1. JwtUserDetailsService является реализацией UserDetailsService.
2. В целом, мы могли бы пропустить этот этап. Но иногда мы делаем это, для обработки случаев блокировки юзера. Т.е. есть токен на месяц. Человека заблокировали в БД, но токен еще валиден. И человек сможет иметь доступ к системе.
3. Login выдает токен, в остальных местах, мы его проверяем в рамках аутентификации.
Надеюсь, я верно понял ваши вопросы и смог на них ответить.
@@EugeneSuleimanov Большое спасибо за уделенное мне время, теперь все устаканилось в голове.
Добрый день! Проясните, пожалуйста, такой момент.
В методе контроллера login вызывается
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, requestDto.getPassword()));
Какая реализация используеться для authenticationManager?
Каким образом он понимает, как валидировать пароль и логин?
Спасибо заранее!
Правильно ли будет сохранять jwt в БД?
Спасибо огромное за видео!
Возник вопрос: когда пишу в AuthenticationRestControllerV1 аннотацию Autowired у конструктора, то authenticationManager подсвечивается красным и пишет: No beans of "AuthenticationManager" type not found. В чём может быть причина?
Если у кого-то была такая ошибка, то она возникает по причине того, что в SecurityConfig у authenticationManager() нужно добавить @Bean
Спасибо за отзыв.
Если работает корректно, то вероятнее всего, проблемы в настройках idea. Если нет - нужно поискать ошибку в коде. Особенно, аннотации.
@@AquaChanneOne только сейчас увидел ответ
@@EugeneSuleimanov Можно ещё вопрос спросить:
Открыл ваш проект, ничего не менял, в нём ошибка возникает в классе JwtTokenProvider у поля userDetailsService:
Could not autowire. There is more than one bean of 'UserDetailsService' type.
Beans: inMemoryUserDetailsManager (UserDetailsServiceAutoConfiguration. class)
С чем это может быть связано? Также и у меня в моём проекте, который я создавал параллельно вашему видео, такая же ошибка.
@@AquaChanneOneОшибка с authenticationManager, в моем случае, возникла, потому что забыл на класс SecurityConfig повесить аннотацию @Configuration
Здравствуйте, Евгений. Возможо, где то просмотрел, но не могу найти связть между hasRole("Admin") и записью ROLE_ADMIN, которую мы добавили в базу. Как происходит проверка на админа, как спринг узнает, что этот пользователь админ? Спасибо.
Добрый вечер, Данил. Это "вшитая" логика spring security
Очень долго пытался разбраться почему не работает jwtTokenProvider так и не смог. Постоянно получаю различные исключения при разных ситуациях. Так и не могу ни как заставить его работать
Ролики супер, огромное спасибо, но запускайте свои проекты пожалуйста перед Push'ем на гит , а то со скаченного проекта с гитхаба выходит карусель при создании бинов, я конечно ее решил, и тем самым понял ваш урок еще лучше, может быть вы так и планировали ?)))
Заливал довольно давно и на тех версиях и в той конфигурации, насколько я помню, это работало. Если нет, то прошу прощения за неудобства.
P.S.: если там ошибка, то это мой фол, а не хитрый план :)
если уже используешь ломбок, то можно юзать аннотации @RequiredArgsConstructor, чтобы не писать конструктор
может, ради Autowired
Спасибо Вам! В ру сегменте очень не хватает качественных уроков!
Будет ли ещё видео, так как от Вас год ждал видео))
Спасибо за отзыв, Александр ) Постараюсь выкладывать чаще. Сейчас работаю над серией видео по Java 11. Но, основная работа занимает много времени. Постараюсь к середине лета добить Java 11 и выложить.
@@EugeneSuleimanov лучше spring. Все же большинство людей смотрят, что бы устроиться на работу. Посмотрите на сегмент хибернейта, спринга. Его практически нет. Мало кто хороше рассказывает. И критически мало видео где создают свое веб приложение. Я знаю только ОДНОГО автора который создаёт свое приложение, но все же не совсем для новичков. Не разжёвывает. Вот у вас выходит ещё. Но и все.
@@GoPetr как вариант. Spring 5 есть заготовки, возможно, переключусь на этот цикл видео. Спасибо за совет
@@EugeneSuleimanov было бы круто! Спасибо!
@@EugeneSuleimanov Также за Spring Boot, по Java 11 другие блогеры расскажут, а вот второго Евгения нету на RUclips который также круто будет по spring учить ;)
Благодарю за видео! разбираю сейчас данную тему. не могу понять в каком месте spring security сверяется с базой данных? у меня BadCredentialsException на строчке authenticationManager.authenticate.. база данных postge
Офигенно
Спасибо за комментарий :)
А зачем вручную создавать таблицы,если jpa автоматически создаст их?
Евгений, здравствуйте! Урок хороший, но мне интересно, существует ли возможность создать фичу "remember me" в связке Spring + JWT?
Добрый день, Анна. Вы имеете в виду - "не выходить из приложения" или сохранить пароль и логин на клиенте?
@@EugeneSuleimanov имеется в виду, что авторизованный в режиме "remember me" пользователь может закрыть браузер, а через неделю открыть приложение, и ему не нужно будет авторизовываться, он будет иметь доступ к защищенным ресурсам без введения логина и пароля. Мне кажется, фичу "remember me" можно сделать следующим образом: ставим jwt expiration time на 30 дней на бекенде. На фронтенде пользователь, если он включил режим remember me, то ему в ответ прилетит jwt-токен, который будет сохранен в постоянном хранилище браузера (local storage). И будет использоваться 30 дней, пока не истечет. И при logout'е просто удаляем из постоянного хранилища токен. Если пользователь не будет использовать режим remember me, то сохраняем токен только в сессионном хранилище (session storage), и тогда при закрытии вкладки токен исчезнет. Насколько хорош такой вариант?P.S. в ангуляре вышеперечисленные действия очень легко осуществляются, вопрос - безопасно ли это и в целом, насколько хороша такая практика?
@@annakhuseinova8162 в этом плане - да, это возможно реализовать. С точки зрения безопасности - не думаю, что это проблема.
@@EugeneSuleimanov спасибо за Ваш ответ) И спасибо за уроки :)
@@annakhuseinova8162 был рад помочь :) Спасибо за отзыв
В данной реализации при каждом обращении пользователя фильтр JwtTokenFilter через jwtTokenProvider обращается к базе данных, и тем самым, сводит преимущества JWT токенов на нет. Чтобы это исправить, нужно переписать метод getAuthentication так, чтобы он собирал объект Authentication на основе тех данных, которые есть в самом токене (Claims). Поправьте меня, если ошибаюсь. А так большое спасибо за Ваш видео урок!
Спасибо за комментарий!
Да, вы правы, мы могли бы сделать и так. Здесь единственное преимущество в том, что изменение статуса мгновенно отразится на аутентификации.
Попробовал сделать такую же авторизацию на тестовом проекте и столкнулся с тем, что отсутствует WebSecurityConfigurerAdapter. В последних версиях Spring Security его нет. Целый день пытаюсь адаптировать пример из видео под использование без адаптера. Будет ли подобное видео с новой версией секьюрити или разбор что изменилось и как теперь с этим работать?
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Autowired
private JwtAuthenticationFilter jwtAuthenticationFilter;
@Autowired
private CustomUserDetailsService customUserDetailsService;
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(customUserDetailsService).passwordEncoder(passwordEncoder());
}
@Bean
public JwtAuthenticationFilter jwtAuthenticationFilter() {
return new JwtAuthenticationFilter();
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/api/auth/**").permitAll()
.antMatchers("/api/**").authenticated()
.and()
.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
return http.build();
}
}
Это примерно. Т.е. используются аннотации и SecurityFilterChain. Это должно помочь.
@@EugeneSuleimanov спасибо!
Спасибо! Но , сложновато , конечно ... долго писали базу и модель , в итоге , что касается security , видимо, автор подустал и пошла спешка
Большое спасибо за урок! Не смог понять только, как сделать так, чтобы при отправке POST /auth/login передавался зашифрованный пароль и сравнивался напрямую с тем, что лежит в базе.
Никак. Пароль в данном демоуроке не шифруется, а хешируется. Плюс "приготовление" ХЭШа идет с солью. Т.е. один и тот же пароль будет всякий раз давать разный ХЭШ. Но всегда есть возможность имея оригинальный пароль проверить, а от него ли ХЭШ, что здесь и делается. А если вас волнует передача пароля в открытом виде, то вас больше должна волновать передача токена в открытом виде. Эта операция выполняется куда чаще. Но! Взаимодействие клиент-сервер здесь идет по протоколу HTTP. Всего то нужно перейти на HTTPS запросы, что исключит возможность узнать пароль путем анализа трафика. А для этого просто "прикрутите" SSL сертификат к Spring Boot. В Инете полно инфы на эту тему.
Добрый день Евгений. Спасибо за качественные ролики. Хорошо что Вы в безопасном месте. Просматривая этот ролик в очередной раз, возник вопрос, на который я так и не смог найти ответ. А вопрос вот в чем. При авторизации пользователя в контроллере в методе "login" мы используем такую строчку: "authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, requestDto.getPassword()));" и в случае если логин и пароль не совпадают, получаем исключение, а именно Spring проводит данное сравнение, а именно как он и где берет данные из БД? Может быть вы подскажите. Спасибо.
Спасибо за отзыв! Это "подкапотная логика спринга". Он сам идет в БД и сверяет соль пароля с солью переданного пароля. Если нет совпадения - кидает исключение.
@@EugeneSuleimanov Спасибо. Еще момент, получается в БД он идет, но пологаясь на UserDetails модель?
@@DankoBLR да, верно
@@EugeneSuleimanov Спасибо за ответы. Если вы не против, хотел бы еще пару вопросов задать. Получается в Security Context лежат действующие токены. Но если реализовать refresh токен, его необходимо хранить в БД. Если его привязать к записе пользователя отдельной ячейкой, мы получим разлогинивание на втором устройстве после того, как протухнит токен доступа. Все же лучше хранить тогда токен обновления в отдельной таблице? Как часто тогда лучше их чекать на протухание и стоит ли их удалять или после протухания просто выстывлять им флаг удаления или фалаг не активности? Спасибо.
@@DankoBLR в данном случае процесс строится несколько иначе, обычно. Здесь неплохое описание:
www.codeusingjava.com/jwt/jwt4
Спасибо за видос, было полезно. У меня возник вопрос: почему когда неправильный пароль то в ответе возвращается 403 Forbidden а не 401? Как в этом случае вернуть какую то осмысленную ошибка а не "Access Denied"
Спасибо за отзыв :). Касательно вашего вопроса - эту ситуацию можно обработать в контроллере и возвращать нужный ответ (AuthenticationRestControllerV1). Метод login в блоке catch.
Eugene Suleimanov а будет видос на тему рефреш токена?
@@Nucl3aRxxx сейчас хочу снять ещё одно видео по JWT с более подробным объяснением и обновлением токена. Но, к сожалению, из-за работы времени остаётся крайне мало :(
А что такое Claimes ?
Здравствуйте, Евгений! Может подскажите как перехватывать исключения внутри пакета jwt.
ControllerAdvice - перехватывает только все то находится на уровне контроллеров =(. А вот фильтрация происходит раньше, и вот как перехватить исключения ума не приложу
Может сталкивались с этим?
Добрый день!
Если вы знаете конкретное
исключение, то просто через глобальный обработчик можно сделать.
reflectoring.io/spring-boot-exception-handling/
Может на спринг буте 2.1.4 это работает, но я встретился с проблемой циклической зависимости, исправил за счет того что вынес бин passwordEncoder в отдельный конфиг класс
вопрос по JPA и liquibase.
Что если задать в XML только таблицы, а поля оставить на JPA? Все корректно отработает ?
Не готов ответить со 100% уверенностью. Но, мне кажется, что возникнет ошибка. И сам подход не совсем корректный, с моей точки зрения. Если мы используем средства контроля версионности БД, то лучше использовать её полностью.
@@EugeneSuleimanov понял, спасибо
@@EugeneSuleimanov и если можно, еще один вопрос, уже больше по авторизации.
Можно ли как то прикрутить эту авторизацию между другими микросервисами, и если да, что стоит взять за основу, oauth2 или как то по другому ?
Может быть подскажете, как сделать фильтрацию с динамическим количеством параметров на бэкэнде(restful).
Думаю, это поможет:
spring.io/blog/2011/04/26/advanced-spring-data-jpa-specifications-and-querydsl/
Вопрос, у меня не работает log.info(""); в чём может быть проблема?и ещё, вы в коде не делаете geters и seters, но они работают, у меня же выдает ошибки если я их не создам, в чём может быть дело? только начал изучать JAVA, не судите строго.
Добрый день, Алексей. Вероятнее всего, проблема в настройках IDEA. Вам нужно зайти в Settings и найти Ebnable annotation processing. И поставить галочку. Это должно решить проблему. Если не поможет пишите, попробуем другие варианты. P.S.: задавайте вопросы - ничего страшного. Всегда постараюсь помочь.
@@EugeneSuleimanov Всё решилось установкой плагина Lombok. вдруг кому поможет) Спасибо за отличный урок!
@@user-bl1ui9fu3b да, это самый первый этап. Забыл написать про него. Спасибо )
@@EugeneSuleimanov хорошо нашел этот коммент. Так же ломал голову и не понимал что сделал не так. Потом добавил гетеры и сеттеры, после этого и догнал, что проблема в Lombok
Офигенный видос. Но вот только я немного не понял почему автор пропустил поле password в DTO.
Спасибо за отзыв. Обычно пароль стараются не отдавать ни в каком виде. Он и не нужен, кроме как для смены пароля, а этот функционал выносится в отдельную логику
@@EugeneSuleimanov DTO хорошо, а можно пример как работать с mapstruct ?
В рунете ничего нет по mupstruct ;(((
Круто ! Спасибо! А как по api файлы сохранять и принимать?
Спасибо за отзыв!
По вашему вопросу:
community.postman.com/t/sending-request-with-file-and-text/7385