Это видео - лучшее что я видел про Spring Security. Два часа, в которых собрана только полезная информация, которую самому можно изучать очень долго. Супер! Спасибо! Теперь нужно еще 2 видео о секьюрности: 1. Про скрещивание авторизации на основе Oauth2 (сторонний сервер) + своя БД. 2. Про цепочки фильтров.
@@EugeneSuleimanov Евгений, скажите пожалуйста. Я делаю спринг мвс проект без boot и ориентируюсь на ваше видео. При реализации с JWT ваши html страницы остались активны?
Полноценное кино 🍿 Блокбастер от Женька. Не представляешь, как ты вовремя с этим видео, второй день пытаюсь разобраться с принципом работы Spring Security
посмотрел все внимательно, повторял каждый шаг за Евгением. Итог - приложение работает, я сам ни хрена не понял. Просто чистый лист. АПДЕЙТ! Надо посмотреть несколько раз, раза с третьего заходит как домой. Тема очень сложная как по мне. Спасибо за Ваш труд!
Не знаю как и поблагодарить-то кроме лайка с подпиской. Настолько ценный материал. Делаю свой пет проект, чтобы найти первую работу и твой контет не побоюсь так сказать, играет решающую роль!
Прекрасный материал. Два часа ценнейшей выверенной информации. И тут не только Spring Security, но и еще отличный сборник лучших практик программирования на Java. Больше всего меня поразило, что этот материал записан практически за несколько часов. Одним сплошным потоком. Потрясающе. Спасибо!
по некоторым видео Евгения, готовлюсь к срезам и собесам, будучи стажером Java, это видео очень классное, плюс также много раз смотрел видео по паттернам, огромное спасибо и низкий поклон Евгений!
Евгений, а как теперь связать фронтенд с JWT? С Postman конечно играть прикольно)), но в браузере как-то актуальнее. Куда засунуть токен в постмане - понятно, чтобы получить доступ к страницам. А вот как это все воплощается вне постмана?
@@valdemiros5309 беку все равно, как эти данные буду отправлены. Но, обычно мы просто сохраняем токен в localStorage и через интерцептор добавляем токен в хедеры запросов.
@@EugeneSuleimanov ну так-то понятно, что бэку всеравно)), но тут столкнулся именно с такой задачей - подружить JWT c фронтом и завис... а в сети информации такой практически крупицы...
Отличный видос! Спасибо! Заметил одиин нюанс когда разбирался какую роль играет класс SecurityUser и похоже, что фактически он не нужен. В том плане, что из него используется только статический метод: static UserDetails fromUser(User user) Возможно, стоило его перенести в UserDetailsServiceImpl где он используется а SecurityUser удалить.
Скорее всего тот метод должен был выглядеть как-то так: public static SecurityUser fromUser(User user) { return new SecurityUser( user.getEmail(), user.getPassword(), user.getRole().getAuthorities(), user.getStatus() == Status.ACTIVE); }
Вадим! Автор специально акцентировал, что в данном случае есть кастомный юзер хранимый в БД, а есть юзер который имплементирует User Details. Для новичков это очень важно т.к. возникает путанница с юзерами.
Это было божественно, под конец было ощущение, что все немного быстро(в плане слишком много нового материала на одну минуту ахахаха), но в целом шикарный курс, спасибо вам :) Всем мир
33:00 @Configuration @EnableWebSecurity public class SecurityConfig { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http // cross site request forgery .csrf(csrf->csrf.disable()) .authorizeHttpRequests((authorizeHttpRequests) -> authorizeHttpRequests // access to the root of our app index.html in resources/static .requestMatchers("/").permitAll() // acces to url /api/** where two asterisk means any .requestMatchers(HttpMethod.GET, "/api/**").hasAnyRole(Role.ADMIN.name(), Role.USER.name()) .requestMatchers(HttpMethod.POST, "/api/**").hasRole(Role.ADMIN.name()) .requestMatchers(HttpMethod.DELETE, "/api/**").hasRole(Role.ADMIN.name()) // any request should be authenticated .anyRequest() .authenticated() ) .httpBasic(withDefaults()); return http.build(); } @Bean public InMemoryUserDetailsManager inMemoryUserDetailsManager(){ UserDetails admin = User.builder() .username("admin") .password(passwordEncoder().encode("admin")) .roles("ADMIN") .build(); UserDetails user = User.builder() .username("user") .password(passwordEncoder().encode("user")) .roles("USER") .build(); System.out.println(user.getPassword()); System.out.println(admin.getPassword()); return new InMemoryUserDetailsManager(user, admin); } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } }
54:45 @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http // cross site request forgery .csrf(csrf->csrf.disable()) .authorizeHttpRequests((authorizeHttpRequests) -> authorizeHttpRequests // access to the root of our app index.html in resources/static .requestMatchers("/").permitAll() .anyRequest() .authenticated() ) .formLogin(form -> form // URL to our custom login page accessible for all .loginPage("/auth/login").permitAll() // URL to success page .defaultSuccessUrl("/auth/success") ) .logout(logout -> logout // logout is possible with post request to that url .logoutRequestMatcher(new AntPathRequestMatcher("/auth/logout", "POST")) // actual session invalidating .invalidateHttpSession(true) // removing authentication from security context .clearAuthentication(true) .deleteCookies("JSESSIONID") .logoutSuccessUrl("/auth/login") ); //.httpBasic(withDefaults()); return http.build(); }
1:13:57 Здесь сложность возникла только с тем как установить свой AuthenticationProvider @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http // cross site request forgery .csrf(csrf->csrf.disable()) .authorizeHttpRequests((authorizeHttpRequests) -> authorizeHttpRequests // access to the root of our app index.html in resources/static .requestMatchers("/").permitAll() .anyRequest() .authenticated() ) .formLogin(form -> form // URL to our custom login page accessible for all .loginPage("/auth/login").permitAll() // URL to success page .defaultSuccessUrl("/auth/success") ) .logout(logout -> logout // logout is possible with post request to that url .logoutRequestMatcher(new AntPathRequestMatcher("/auth/logout", "POST")) // actual session invalidating .invalidateHttpSession(true) // removing authentication from security context .clearAuthentication(true) .deleteCookies("JSESSIONID") .logoutSuccessUrl("/auth/login") ) .authenticationProvider(daoAuthenticationProvider()); //.httpBasic(withDefaults()); return http.build(); }
Спасибо за видео. Как всегда все отлично. 1) В @PreAuthorize лучше не строки прописывать, а из enum Permission брать. Т.к. в будущем, если переименуете, сложно будет по коду искать. А так IDEA через refactor все сама исправит по всему коду. 2) На 1:30:05 - проверку на expiration необязательно делать, т.к. в ParseClaimsJws она уже проверяется 3) И конструкторы лучше тоже через lombok создавать 4) На 1:47:05 я б из контроллера код в authenticate вынес в отдельный сервис. Контроллеры лучше делать меньше
Да через enum брать конечно хорошо, но стандартно - указывая полный путь, очень печально. В противном случае надо еще поплясать с бубном и написать кучу кода.
@@ВолодимирВасилишин-я4ч в классе Role в методе getAuthorities() меняем new SimpleGrantedAuthority(permission.getPermission()) на new SimpleGrantedAuthority(permission.name()) и теперь в классе контроллере можно писать так @PreAuthorize("hasAuthority('PERMISSION_WRITE')")
Не мало информации просмотрел на тему spring security и могу однозначно сказать,что Ваша подача информации одна из самых лучших... хотя бы для меня лично,но думаю все с этим согласны! Низкий Вам поклон,добрый человек!
Наконец-то, заждались уже от Евгения видео. Спасибо, как раз,то что надо, чётко и по делу. Такой вопрос где обещанные видео с собеседованиями? (кроме тех которые уже выложены)
Спасибо за отзыв! 1 собеседование не состоялось, теперь ищу интересного кандидата. Как только будет человек с интересным опытом - запишу и обязательно опубликую.
Если не ошибаюсь, то, кажется, вместе return User() в методе fromUser(user: User), вам надо было вернуть SecurityUser(). Разве не для этого мы имплементили в этом классе UserDetails и оверрайдили нужные интерфейсу методы? Не хочу показаться невежливым и т.д. Я только учусь, но, показалось, что тут нарушена логика немного.
Прямо благодарность! (Как раз обвешиваю своё pet приложение для прохождения собеседования. Spring security подъехал just in time : ) ) Всё внедрилось как часики.
Автору огромное спасибо!!!) Видео очень помогло в первичном погружении в spring security, особенно про jwt, если планируются новые видео, то очень жду, теперь будет проще начать изучение проф литературы Еще не плохо бы было, если автор рассказал/показал примеры с OAuth2.1
Евгений, здравствуйте, зачем мы возвращаем org.springframework.security.core.User (1:09:15), если мы создали свою имплементацию UserDetails - SecurityUser? В итоге потом наша имплементация нигде не используется
Привет. Спасибо за видео 1:17:19 1:18:16 оговорки, пейлоад токена не зашифрован, а закодирован и раскодировать содержимое токена может любой. Ключ нужен для того, чтобы убедиться, что пейлоад токена не редактировался. Приватную информацию в пейлоаде такого токена передавать не стоит.
Евгений, большое Вам спасибо за видео! Я огромная Ваша поклонница, постоянно Вас смотрю!!! Подскажите, пож-та, если не сложно: в ветке аутентификации с БД у меня не работает дебаг в спринг буте. Я вижу, что дело в классе KeyStore, а именно KeyStoreName = null. Попыталась разобраться - я так понимаю, это настройки ssl. Знаний решить проблему пока не хватает, и я не понимаю, почему у Вас на видео дебаг работает, а у меня нет? Буду благодарна, если ответите!
И не только его :) docs.spring.io/spring-security/site/docs/5.2.9.RELEASE/reference/html/ Даже порядок глав почти не менялся > www.baeldung.com/learn-spring-security-core-course > ru-vid.com/video/%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE-tWcqSIQr6Ks.html > ru-vid.com/video/%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE-her_7pa0vrg.html > ru-vid.com/video/%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE-Of4HFbsPKqk.html А если вы откроете еще и docs.oracle.com/javase/specs/jls/se17/html/index.html То к 99% курсов будут вопросы. Поэтому мой совет не меняется уже много лет - читайте документацию.