В прошлый раз небольшой партнер предположил, что анализ исходного кода слишком скучен.Если мы сможем комбинировать шаблоны проектирования, это поможет всем понять исходный код Spring Security, и в то же время мы сможем просмотреть целую волну шаблонов проектирования.
Поэтому Сонг Гэ сегодня попробует всю статью и расскажет вам о шаблонах проектирования, связанных с Spring Security.Однако в Spring Security по-прежнему много шаблонов проектирования.Сонг Гэ расскажет о некоторых здесь, а остальные Друзья, пожалуйста, оставляйте комментарии.
1. Паттерн шаблонного метода
Шаблон шаблона (template method pattern) — это шаблон абстрактного класса, который публично определяет метод для его выполнения. Его подклассы могут переопределять реализацию метода по мере необходимости, но вызовы будут выполняться способом, определенным в абстрактном классе, который является шаблоном поведения.
Преимущества шаблонного метода заключаются в следующем:
- Общая часть кода извлекается из родительского класса, что удобно для повторного использования и расширения кода.
- Некоторые методы реализуются подклассами, а подклассы могут добавлять соответствующие функции путем расширения, что соответствует принципу открытого-закрытого.
Недостатки следующие:
- Подкласс должен быть определен для каждой отдельной реализации, что приводит к увеличению количества классов, более сложной системе и более абстрактному дизайну.
- Абстрактный метод в родительском классе реализуется подклассом, и результат выполнения подкласса повлияет на результат родительского класса, что усложняет понимание кода.
После знакомства с шаблоном метода шаблона вы, возможно, догадались, где шаблон метода шаблона используется в Spring Security.
Привожу несколько простых примеров.
Первый пример — это дизайн класса AbstractUserDetailsAuthenticationProvider. Всем известно, что этот класс используется для проверки, и в этом методе определена логика аутентификации, но этот класс определяет два абстрактных метода:
- retrieveUser Этот метод извлекает объект пользователя из источника данных.
- AdditionalAuthenticationChecks Этот метод используется для дополнительной проверки (проверки учетных данных для входа)
Эти два абстрактных метода реализованы в DaoAuthenticationProvider. Реализация DaoAuthenticationProvider заключается в загрузке пользователей из базы данных, а учетные данные входа для проверки по умолчанию также являются паролями проверки.
Если ваш источник данных поступает из другого места или учетные данные для входа не являются паролями, то пользовательский класс наследуется от AbstractUserDetailsAuthenticationProvider и переопределяет в нем эти два метода.
2. Модель цепочки ответственности
Шаблон цепочки ответственности, в котором обычно каждый получатель содержит ссылку на другого получателя, если один объект не может обработать запрос, он передает тот же запрос следующему получателю и так далее. В этом процессе клиенту нужно только отправить запрос в цепочку ответственности, и ему не нужно заботиться о деталях обработки запроса и процессе передачи запроса, поэтому цепочка ответственности отделяет отправителя запроса. и обработчик запроса.
Преимущества модели цепочки ответственности заключаются в следующем:
- Уменьшите связь между объектами.
- Повышенная масштабируемость системы.
- При изменении рабочего процесса члены цепочки могут быть динамически изменены или их порядок может быть мобилизован.
- Упрощает соединение между объектами, каждый объект должен поддерживать ссылку только на своего преемника, а не на все другие обработчики.
- Ответственность разделена, каждый класс должен выполнять только ту работу, которую он должен выполнять, в соответствии с принципом единой ответственности класса.
Недостатки следующие:
- По сравнению с более длинной цепочкой ответственности обработка запроса может включать в себя несколько объектов обработки, что в определенной степени повлияет на производительность системы.
- Рациональность установления цепочки ответственности гарантируется клиентом, что увеличивает сложность клиента.
Очевидно, что цепочка фильтров в Spring Security представляет собой шаблон цепочки ответственности. После поступления запроса он обрабатывается один за другим фильтрами в цепочке фильтров.Каждый фильтр в цепочке фильтров имеет разные функции и не мешает друг другу.Также мы можем динамически настраивать фильтрацию в цепочке фильтров через фильтр HttpSecurity (т.е. добавлять/удалять фильтры в цепочке фильтров).
Конкретный код находится в FilterChainProxy$VirtualFilterChain следующим образом:
Тогда давайте посмотрим на VirtualFilterChain:
private static class VirtualFilterChain implements FilterChain {
private final FilterChain originalChain;
private final List<Filter> additionalFilters;
private final FirewalledRequest firewalledRequest;
private final int size;
private int currentPosition = 0;
private VirtualFilterChain(FirewalledRequest firewalledRequest,
FilterChain chain, List<Filter> additionalFilters) {
this.originalChain = chain;
this.additionalFilters = additionalFilters;
this.size = additionalFilters.size();
this.firewalledRequest = firewalledRequest;
}
@Override
public void doFilter(ServletRequest request, ServletResponse response)
throws IOException, ServletException {
if (currentPosition == size) {
if (logger.isDebugEnabled()) {
logger.debug(UrlUtils.buildRequestUrl(firewalledRequest)
+ " reached end of additional filter chain; proceeding with original chain");
}
// Deactivate path stripping as we exit the security filter chain
this.firewalledRequest.reset();
originalChain.doFilter(request, response);
}
else {
currentPosition++;
Filter nextFilter = additionalFilters.get(currentPosition - 1);
if (logger.isDebugEnabled()) {
logger.debug(UrlUtils.buildRequestUrl(firewalledRequest)
+ " at position " + currentPosition + " of " + size
+ " in additional filter chain; firing Filter: '"
+ nextFilter.getClass().getSimpleName() + "'");
}
nextFilter.doFilter(request, response, this);
}
}
}
- Класс VirtualFilterChain сначала объявляет пять глобальных свойств: originalChain представляет исходную цепочку фильтров, то есть Web Filter; AdditionalFilters представляет цепочку фильтров в Spring Security; firewalledRequest представляет текущий запрос; size представляет количество фильтров в цепочке фильтров; currentPosition — это индекс при обходе цепочки фильтров.
- Метод doFilter — это процесс выполнения фильтров один за другим в Spring Security.
currentPosition == size
, указывая на то, что цепочка фильтров выполнена.В это время он входит в исходный метод цепочки фильтров, вызывая originalChain.doFilter, а также выходит из цепочки фильтров Spring Security. В противном случае удалите фильтры в цепочке фильтров Spring Security из AdditionalFilters и вызовите метод doFilter один за другим. nextFilter.doFilter — это цепочка фильтров, идущая вниз один за другим.
Для ознакомления с FilterChainProxy см.:Глубокое понимание FilterChainProxy [исходный код]
3. Режим стратегии
Шаблон стратегии, который определяет серию алгоритмов, инкапсулирует каждый алгоритм и делает их взаимозаменяемыми. Режим политики позволяет изменять алгоритм независимо от клиентов, которые его используют, также известный как режим политики (Policy).
Преимущества паттерна стратегии:
- Режим стратегии обеспечивает идеальную поддержку принципа «открыто-закрыто».Пользователи могут выбирать определенные стратегии без изменения исходной системы, а также могут гибко расширять новые стратегии.
- Шаблон политики предоставляет способ управления связанными политиками.
- Шаблон стратегии предоставляет способ замены отношения наследования.
- Используйте шаблон стратегии, чтобы избежать использования нескольких операторов условного перехода.
Недостатки шаблона стратегии:
- Клиент должен знать все классы политик и решать, какой из них использовать.
- Шаблон стратегии приведет к множеству классов стратегий (количество объектов можно в определенной степени уменьшить, используя шаблон легковеса).
Есть также несколько мест, где шаблон стратегии используется в Spring Security.
Во-первых, это хранение информации для входа пользователя.
В методе определения хранилища информации о пользователе для входа в SecurityContextHolder определены три разные стратегии:
public class SecurityContextHolder {
// ~ Static fields/initializers
// =====================================================================================
public static final String MODE_THREADLOCAL = "MODE_THREADLOCAL";
public static final String MODE_INHERITABLETHREADLOCAL = "MODE_INHERITABLETHREADLOCAL";
public static final String MODE_GLOBAL = "MODE_GLOBAL";
public static final String SYSTEM_PROPERTY = "spring.security.strategy";
private static String strategyName = System.getProperty(SYSTEM_PROPERTY);
private static SecurityContextHolderStrategy strategy;
}
Пользователи могут выбирать, какую стратегию использовать! Подробнее см.:В Spring Security я просто хочу получить информацию для входа пользователя из дочернего потока, что мне делать?
Другой — управление параллелизмом сеансов.
В методе AbstractAuthenticationProcessingFilter#doFilter есть следующий код:
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
//省略
sessionStrategy.onAuthentication(authResult, request, response);
//省略
}
Это шаблон стратегии.
Управление параллелизмом сеанса может относиться к:
- Что такое атака с фиксацией сеанса? Как защититься от атак фиксации сеанса в Spring Boot?
- Развертывание кластера, как Spring Security обрабатывает совместное использование сеансов?
Конечно, таких примеров гораздо больше, поэтому я не буду перечислять их все.
4. Прокси-режим
Шаблон прокси: укажите прокси для объекта, а прокси-объект управляет ссылкой на исходный объект.Это шаблон структуры объекта.
Преимущества режима прокси:
- В определенной степени снижается степень связанности системы.
- Прокси-объекты могут расширять функциональные возможности целевого объекта.
- Прокси-объект может защитить целевой объект.
недостаток:
- Добавление прокси между клиентом и реальным объектом может привести к замедлению обработки запросов.
- Повышенная сложность системы.
Наиболее важным применением режима прокси в Spring Security является процесс связывания фильтра Spring Security с веб-фильтром с использованием DelegatingFilterProxy, предоставляемого Spring, что является типичным режимом прокси:
public class DelegatingFilterProxy extends GenericFilterBean {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
// Lazily initialize the delegate if necessary.
Filter delegateToUse = this.delegate;
if (delegateToUse == null) {
synchronized (this.delegateMonitor) {
delegateToUse = this.delegate;
if (delegateToUse == null) {
WebApplicationContext wac = findWebApplicationContext();
if (wac == null) {
throw new IllegalStateException("No WebApplicationContext found: " +
"no ContextLoaderListener or DispatcherServlet registered?");
}
delegateToUse = initDelegate(wac);
}
this.delegate = delegateToUse;
}
}
// Let the delegate perform the actual doFilter operation.
invokeDelegate(delegateToUse, request, response, filterChain);
}
}
Конечно, есть много других мест, где также используется режим прокси, поэтому я не буду перечислять их все, друзья могут оставить сообщение для добавления.
5. Режим адаптера
Адаптер Pattern (режим адаптера), научное название зарядного устройства для мобильного телефона, которое обычно используют все, называется адаптером питания, и его функция заключается в преобразовании напряжения 220 В в напряжение 5 В, доступное для мобильного телефона. Таким образом, шаблон адаптера на самом деле является аналогичной функцией, преобразующей один интерфейс в другой интерфейс, который нужен клиенту, а шаблон адаптера позволяет классам с несовместимыми интерфейсами работать вместе. Режим адаптера далее делится на режим адаптера класса, режим адаптера объекта и режим адаптера интерфейса.
Преимущества шаблона адаптера:
- Разделение путем введения класса адаптера для повторного использования существующего класса адаптера без изменения исходного кода.
- Повышенная прозрачность и возможность повторного использования классов.
- Он имеет лучшую гибкость и расширяемость.
недостаток:
- Поскольку Java не поддерживает множественное наследование, за один раз можно адаптировать не более одного класса адаптера, а целевой абстрактный класс может быть только абстрактным, а не конкретным классом, и его использование имеет определенные ограничения.
В Spring Security также есть много шаблонов адаптеров, таких как наш самый распространенный WebSecurityConfigurerAdapter, который позволяет двум изначально не связанным WebSecurity и HttpSecurity работать вместе.
Подробнее см.:Глубокое понимание WebSecurityConfigurerAdapter [исходный код]
6. Режим строителя
Шаблон Builder отделяет построение сложного объекта от его представления, так что один и тот же процесс построения может создавать разные объекты.Пользователям нужно только указать тип и содержимое сложного объекта, чтобы построить объект, без необходимости знать конкретную сборку детали внутри.
Преимущества режима строителя:
- Отделите сам продукт от процесса создания продукта, чтобы один и тот же процесс создания мог создавать разные объекты продукта, при этом клиенту не нужно было знать внутренние детали продукта.
- Каждому продукту соответствует билдер, пользователи могут создавать разные продукты с разными билдерами, а сами билдеры могут легко модифицировать или добавлять.
- Более детальный контроль над процессом создания продукта.
недостаток:
- Создаваемые продукты должны иметь определенное сходство, если разница слишком велика, это не подходит для шаблона строителя.
- Сложность самого продукта увеличивает сложность строителя.
Есть также много вариантов использования режима построителя в Spring Security, например, типичный AuthenticationManagerBuilder, объект, который он хочет построить, называется AuthenticationManager, а соответствующий метод построения — build. В обычном режиме построителя имя класса построителя заканчивается на builder, а метод построения называется build().
Для AuthenticationManagerBuilder см.:Глубокое понимание AuthenticationManagerBuilder [исходный код]одна статья.
7. Шаблон наблюдателя
Наблюдатель (режим наблюдателя) относится к отношениям зависимости "один ко многим" между несколькими объектами. Когда состояние объекта изменяется, все объекты, которые зависят от него, уведомляются и автоматически обновляются. Режим наблюдателя также называется "публикация-подписка". паттерн модель-представление, который является паттерном поведения объекта.
Преимущества шаблона Observer:
- Отношения связи между целью и наблюдателем уменьшаются, и они представляют собой абстрактные отношения связи.
недостаток:
- Зависимости между целью и наблюдателем полностью не разрешены, и есть вероятность циклических ссылок.
- Когда объектов-наблюдателей много, эффективность выполнения программы снижается.
В среде Spring шаблон наблюдателя используется для реализации функции обработки событий ApplicationContext. Spring предоставляет нам класс ApplicationEvent и интерфейс ApplicationListener для включения обработки событий. Любой bean-компонент в приложении Spring, реализующем интерфейс ApplicationListener, будет получать сообщения, отправляемые ApplicationEvent в качестве издателя событий. Здесь публикатором события является субъект (Subject) и наблюдатель (Observer) компонента, который реализует ApplicationListener.
В частности, в Spring Security, такие как выпуск успешных событий входа в систему, событие разрушения сеанса и т. Д., Все шаблоны наблюдателя.
Например, метод AbstractAuthenticationProcessingFilter#successfulAuthentication:
protected void successfulAuthentication(HttpServletRequest request,
HttpServletResponse response, FilterChain chain, Authentication authResult)
throws IOException, ServletException {
if (logger.isDebugEnabled()) {
logger.debug("Authentication success. Updating SecurityContextHolder to contain: "
+ authResult);
}
SecurityContextHolder.getContext().setAuthentication(authResult);
rememberMeServices.loginSuccess(request, response, authResult);
// Fire event
if (this.eventPublisher != null) {
eventPublisher.publishEvent(new InteractiveAuthenticationSuccessEvent(
authResult, this.getClass()));
}
successHandler.onAuthenticationSuccess(request, response, authResult);
}
Есть много похожих, таких как события уничтожения сеанса и т. д. (см.Spring Security автоматически удаляет предыдущего пользователя, вошедшего в систему, одна конфигурация выполнена!), я не буду перечислять их все здесь.
8. Декоративный режим
Декоратор (декоративный режим) относится к режиму, который динамически добавляет некоторые дополнительные функции к объекту без изменения существующей структуры объекта.
Преимущества режима украшения:
- Функциональность класса может быть гибко расширена.
недостаток:
- Добавлено много подклассов, что делает программу очень сложной.
В Spring Security также есть много применений шаблона декоратора. Наиболее типичным является то, что при прохождении запроса через цепочку фильтров он будет постоянно изменяться, а его функция будет постоянно корректироваться.Многие классы запроса оформлены через режим оформления, например:
- HeaderWriterRequest
- FirewalledRequest
- StrictHttpFirewall
- SaveToSessionRequestWrapper
- ...
Подождите, похожих много, поэтому я не буду повторять их по порядку.
резюме
Spring Security Songge все еще сериализуется, и в будущем после сериализации будут обобщены другие шаблоны проектирования. Вот восемь, которыми можно поделиться с друзьями. Если у вас есть собственное мнение, вы можете оставить сообщение для добавления.