Ызкштп. Оглавление Введение 61. Что такое инверсия контроля (IoC) и внедрение зависимостей (DI) Как они реализованы в
Скачать 1.17 Mb.
|
Servlet Filter, но в отличие от последнего он просто позволяет настраивать предварительную обработку с возможностью запретить выполнение самого обработчика и настраивать постобработку. Согласно документации Spring, фильтры более мощные, например, они позволяют обмениваться объектами запроса и ответа, которые передаются по цепочке. Это означает, что фильтры работают больше в области запроса/ответа, в то время как HandlerInterceptors являются бинами и могут обращаться к другим компонентам в приложении. Обратите внимание, что фильтр настраивается в web.xml, а HandlerInterceptor в контексте приложения. Java Listener Listener (Слушатель) - это класс, который реализует интерфейс javax.servlet.ServletContextListener. Он инициализируется только один раз при запуске веб- приложения и уничтожается при остановке веб-приложения. Слушатель сидит и ждет, когда произойдет указанное событие, затем «перехватывает» событие и запускает собственное событие. Например, мы хотим инициализировать пул соединений с базой данных до запуска веб-приложения. ServletContextListener - это то, что нам нужно, он будет запускать наш код до запуска веб-приложения. Все ServletContextListeners уведомляются об инициализации контекста до инициализации любых фильтров или сервлетов в веб-приложении. Все ServletContextListeners уведомляются об уничтожении контекста после того, как все сервлеты и фильтры уничтожены. Чтобы создать свой Listener нам достаточно создать класс, имплементирующий интерфейс ServletContextListener и поставить над ним аннотацию @WebListener: @WebListener public class MyAppServletContextListener implements ServletContextListener { //Run this before web application is started @Override public void contextInitialized (ServletContextEvent arg0) { System.out.println( "ServletContextListener started" ); } @Override public void contextDestroyed (ServletContextEvent arg0) { System.out.println( "ServletContextListener destroyed" ); } } 30. Можно ли передать в GET-запросе один и тот же параметр несколько раз? Как? Источники: Baeldung - Mapping a Multi-Value Parameter Habr - Spring: вопросы к собеседованию Да, можно принять все значения, используя массив в методе контроллера: http: //localhost:8080/login?name=Ranga&name=Ravi&name=Sathish public String method (@RequestParam(value= "name" ) String[] names){...} или http: //localhost:8080/api/foos?id=1,2,3 ---- IDs are [ 1 , 2 , 3 ] @GetMapping ( "/api/foos" ) @ResponseBody public String getFoos (@RequestParam List { return "IDs are " + id; } 31. Как работает Spring Security? Как сконфигурировать? Какие интерфейсы используются? Источники: Spring - Spring Security Architecture Spring Security Documentation Spring Security API Wikibooks - Технический обзор Spring Security Spring Security обеспечивает всестороннюю поддержку аутентификации, авторизации и защиты от распространенных эксплойтов. Он также обеспечивает интеграцию с другими библиотеками, чтобы упростить его использование. Spring Security - это список фильтров в виде класса FilterChainProxy , интегрированного в контейнер сервлетов, и в котором есть поле List Когда мы добавляем аннотацию @EnableWebSecurity добавляется DelegatingFilterProxy, его задача заключается в том, чтобы вызвать цепочку фильтров (FilterChainProxy) из Spring Security. В Java-based конфигурации цепочка фильтров создается неявно. Если мы хотим настроить свою цепочку фильтров, мы можем сделать это, создав класс, конфигурирующий наше Spring Security приложение, и имплементировав интерфейс WebSecurityConfigurerAdapter. В данном классе, мы можем переопределить метод: @Override protected void configure (HttpSecurity http) throws Exception { http .csrf().disable() .authorizeRequests(); } Именно этот метод конфигурирует цепочку фильтров Spring Security и логика, указанная в этом методе, настроит цепочку фильтров. Основные классы и интерфейсы SecurityContext - интерфейс, отражающий контекст безопасности для текущего потока. Является контейнером для объекта типа Authentication. (Аналог - ApplicationContext, в котором лежат бины). По умолчанию на каждый поток создается один SecurityContext. SecurityContext-ы хранятся в SecurityContextHolder. Имеет только два метода: getAuthentication() и setAuthentication(Authentication authentication). SecurityContextHolder - это место, где Spring Security хранит информацию о том, кто аутентифицирован. Класс, хранящий в ThreadLocal SecurityContext-ы для каждого потока, и содержащий статические методы для работы с SecurityContext-ами, а через них с текущим объектом Authentication, привязанным к нашему веб-запросу. Authentication - объект, отражающий информацию о текущем пользователе и его привилегиях. Вся работа Spring Security будет заключаться в том, что различные фильтры и обработчики будут брать и класть объект Authentication для каждого посетителя. Кстати объект Authentication можно достать в Spring MVC контроллере командой SecurityContextHolder.getContext().getAuthentication() . Authentication имеет реализацию по умолчанию - класс UsernamePasswordAuthenticationToken , предназначенный для хранения логина, пароля и коллекции Authorities. Principal - интерфейс из пакета java.security, отражающий учетную запись пользователя. В терминах логин-пароль это логин. В интерфейсе Authentication есть метод getPrincipal(), возвращающий Object. При аутентификации с использованием имени пользователя/пароля Principal реализуется объектом типа UserDetails. Credentials - любой Object; то, что подтверждает учетную запись пользователя, как правило пароль (отпечатки пальцев, пин - всё это Credentials, а владелец отпечатков и пина - Principal). GrantedAuthority - полномочия, предоставленные пользователю, например, роли или уровни доступа. UserDetails - интерфейс, представляющий учетную запись пользователя. Как правило модель нашего пользователя должна имплементировать его. Она просто хранит пользовательскую информацию в виде логина, пароля и флагов isAccountNonExpired, isAccountNonLocked, isCredentialsNonExpired, isEnabled, а также коллекции прав (ролей) пользователя. Данная информация позже инкапсулируется в объекты Authentication. UserDetailsService - интерфейс объекта, реализующего загрузку пользовательских данных из хранилища. Созданный нами объект с этим интерфейсом должен обращаться к БД и получать оттуда юзеров. AuthenticationManager - основной стратегический интерфейс для аутентификации. Имеет только один метод, который срабатывает, когда пользователь пытается аутентифицироваться в системе: public interface AuthenticationManager { Authentication authenticate (Authentication authentication) throws AuthenticationException; } AuthenticationManager может сделать одну из 3 вещей в своем методе authenticate(): 1. вернуть Authentication (с authenticated=true), если предполагается, что вход осуществляет корректный пользователь. 2. бросить AuthenticationException, если предполагается, что вход осуществляет некорректный пользователь. 3. вернуть null, если принять решение не представляется возможным. Наиболее часто используемая реализация AuthenticationManager - родной класс ProviderManager , который содержит поле private List AuthenticationProvider - интерфейс объекта, выполняющего аутентификацию. Имеет массу готовых реализаций. Также можем задать свой тип аутентификации. Как правило в небольших проектах одна логика аутентификации - по логину и паролю. В проектах побольше логик может быть несколько: Google-аутентификация и т.д., и для каждой из них создается свой объект AuthenticationProvider. AuthenticationProvider немного похож на AuthenticationManager, но у него есть дополнительный метод, позволяющий вызывающей стороне спрашивать, поддерживает ли он переданный ему объект Authentication, возможно этот AuthenticationProvider может поддерживать только аутентификацию по логину и паролю, но не поддерживать Google- аутентификацию: boolean supports (java.lang.Class> authentication) PasswordEncoder - интерфейс для шифрования/расшифровывания паролей. Одна из популярных реализаций - BCryptPasswordEncoder. В случае, если нам необходимо добавить логику при успешной/неудачной аутентификации, мы можем создать класс и имплементировать интерфейсы AuthenticationSuccessHandler и AuthenticationFailureHandler соответственно, переопределив их методы. Как это работает с формой логина и UserDetailsService : ❖ Пользователь вводит в форму и отправляет логин и пароль. ❖ UsernamePasswordAuthenticationFilter создает объект Authentication - UsernamePasswordAuthenticationToken, где в качестве Principal - логин, а в качестве Credentials - пароль. ❖ Затем UsernamePasswordAuthenticationToken передаёт объект Authentication с логином и паролем AuthenticationManager-у. ❖ AuthenticationManager в виде конкретного класса ProviderManager внутри своего списка объектов AuthenticationProvider, имеющих разные логики аутентификации, пытается аутентифицировать посетителя, вызывая его метод authenticate(). У каждого AuthenticationProvider-а: ➢ Метод authenticate() принимает в качестве аргумента незаполненный объект Authentication, например только с логином и паролем, полученными в форме логина на сайте. Затем с помощью UserDetailsService метод идёт в БД и ищет такого пользователя. ➢ Если такой пользователь есть в БД, AuthenticationProvider получает его из базы в виде объекта UserDetails. Объект Authentication заполняется данными из UserDetails - в него включаются Authorities, а в Principal записывается сам объект UserDetails, содержащий пользователя. ➢ Затем этот метод возвращает заполненный объект Authentication (прошли аутентификацию). Вызывается AuthenticationSuccessHandler. ➢ Если логин либо пароль неверные, то выбрасывается исключение. Вызывается AuthenticationFailureHandler. ❖ Затем этот объект Authentication передается в AccessDecisionManager и получаем решение на получение доступа к запрашиваемой странице (проходим авторизацию). 32. Что такое Spring Boot? Какие у него преимущества? Как конфигурируется? Подробно Источники: Habr - Обратная сторона Spring / Spring Boot Habr - Введение в Spring Boot Javatpoint - Learn Spring Boot Tutorial Spring Boot Reference Documentation Spring Boot - Getting Started Spring Boot - это модуль Spring-а, который предоставляет функцию RAD для среды Spring (Rapid Application Development - Быстрая разработка приложений). Он обеспечивает более простой и быстрый способ настройки и запуска как обычных, так и веб-приложений. Он просматривает наши пути к классам и настроенные нами бины, делает разумные предположения о том, чего нам не хватает, и добавляет эти элементы. Spring Boot представляет собой комбинацию Spring Framework и встроенного контейнера сервлетов и отсутствие (или минимальное наличие) конфигурации приложения. Ключевые особенности и преимущества Spring Boot: 1. Простота управления зависимостями (spring-boot-starter-* в pom.xml). Чтобы ускорить процесс управления зависимостями Spring Boot неявно упаковывает необходимые сторонние зависимости для каждого типа приложения на основе Spring и предоставляет их разработчику в виде так называемых starter-пакетов. Starter-пакеты представляют собой набор удобных дескрипторов зависимостей, которые можно включить в свое приложение. Это позволяет получить универсальное решение для всех технологий, связанных со Spring, избавляя программиста от лишнего поиска необходимых зависимостей, библиотек и решения вопросов, связанных с конфликтом версий различных библиотек. Например, если вы хотите начать использовать Spring Data JPA для доступа к базе данных, просто включите в свой проект зависимость spring-boot-starter-data-jpa (вам не придется искать совместимые драйверы баз данных и библиотеки Hibernate). Если вы хотите создать Spring web-приложение, просто добавьте зависимость spring-boot-starter- web, которая подтянет в проект все библиотеки, необходимые для разработки Spring MVC-приложений, таких как spring-webmvc, jackson-json, validation-api и Tomcat. Другими словами, Spring Boot собирает все общие зависимости и определяет их в одном месте, что позволяет разработчикам просто их использовать. Также при использовании Spring Boot, файл pom.xml содержит намного меньше строк, чем в Spring- приложениях. 2. Автоматическая конфигурация. Автоматическая конфигурация включается аннотацией @EnableAutoConfiguration. (входит в состав аннотации @SpringBootApplication) После выбора необходимых для приложения starter-пакетов Spring Boot попытается автоматически настроить Spring-приложение на основе выбранных jar- зависимостей, доступных в classpath классов, свойств в application.properties и т.п. Например, если добавим spring-boot-starter-web, то Spring boot автоматически сконфигурирует такие бины как DispatcherServlet, ResourceHandlers, MessageSource итд Автоматическая конфигурация работает в последнюю очередь, после регистрации пользовательских бинов и всегда отдает им приоритет. Если ваш код уже зарегистрировал бин DataSource — автоконфигурация не будет его переопределять. 3. Встроенная поддержка сервера приложений/контейнера сервлетов (Tomcat, Jetty, итд). Каждое Spring Boot web-приложение включает встроенный web-сервер. Не нужно беспокоиться о настройке контейнера сервлетов и развертывания приложения в нем. Теперь приложение может запускаться само как исполняемый .jar-файл с использованием встроенного сервера. 4. Готовые к работе функции, такие как метрики, проверки работоспособности, security и внешняя конфигурация. 5. Инструмент CLI (command-line interface) для разработки и тестирования приложения Spring Boot. 6. Минимизация boilerplate кода (код, который должен быть включен во многих местах практически без изменений), конфигурации XML и аннотаций. Как происходит автоконфигурация в Spring Boot: 1. Отмечаем main класс аннотацией @SpringBootApplication (аннотация инкапсулирует в себе: @SpringBootConfiguration, @ComponentScan, @EnableAutoConfiguration), таким образом наличие @SpringBootApplication включает сканирование компонентов, автоконфигурацию и показывает разным компонентам Spring (например, интеграционным тестам), что это Spring Boot приложение. @SpringBootApplication public class DemoApplication { public static void main (String[] args) { SpringApplication.run(DemoApplication.class, args); } } 2. @EnableAutoConfiguration импортирует класс EnableAutoConfigurationImportSelector. Этот класс не объявляет бины сам, а использует так называемые фабрики. 3. Класс EnableAutoConfigurationImportSelector смотрит в файл META-INF/spring.factories и загружает оттуда список значений, которые являются именами классов (авто)конфигураций, которые Spring Boot импортирует. Т.е. аннотация @EnableAutoConfiguration просто импортирует ВСЕ (более 150) перечисленные в spring.factories конфигурации, чтобы предоставить нужные бины в контекст приложения. 4. Каждая из этих конфигураций пытается сконфигурировать различные аспекты приложения (web, JPA, AMQP и т.д.), регистрируя нужные бины. Логика при регистрации бинов управляется набором @ConditionalOn* аннотаций. Можно указать, чтобы бин создавался при наличии класса в classpath (@ConditionalOnClass), наличии существующего бина (@ConditionalOnBean), отсуствии бина (@ConditionalOnMissingBean) и т.п. Таким образом наличие конфигурации не значит, что бин будет создан, и в большинстве случаев конфигурация ничего делать и создавать не будет. 5. Созданный в итоге AnnotationConfigEmbeddedWebApplicationContext ищет в том же DI контейнере фабрику для запуска embedded servlet container. 6. Servlet container запускается, приложение готово к работе! 33. Расскажите про нововведения Spring 5 Источники: Spring - What's New in Spring Framework 5.x Shell26 - Новое в Spring 5 ● Используется JDK 8+ (Optional, CompletableFuture, Time API, java.util.function, default methods) ● Поддержка Java 9 (Automatic-Module-Name in 5.0, module-info in 6.0+, ASM 6) ● Поддержка HTTP/2 (TLS, Push), NIO/NIO.2 ● Поддержка Kotlin ● Реактивность (веб-инфраструктура с реактивным стеком, «Spring WebFlux») ● Null-safety аннотации(@Nullable), новая документация ● Совместимость с Java EE 8 (Servlet 4.0, Bean Validation 2.0, JPA 2.2, JSON Binding API 1.0) ● Поддержка JUnit 5 + Testing Improvements (conditional and concurrent) ● Удалена поддержка: Portlet, Velocity, JasperReports, XMLBeans, JDO, Guava |