Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Краткий экскурс в Spring Security (core)

Краткий экскурс в Spring Security (core)

Слайды вводной лекции о фреймворке Spring Security

Vladimir Plizga

September 15, 2020
Tweet

More Decks by Vladimir Plizga

Other Decks in Programming

Transcript

  1. Краткий экскурс
    в Spring Security
    (core)

    View Slide

  2. 2
    1. Теория
    2.

    3. Практика
    3. Применение
    План

    View Slide

  3. 3
    Цель

    View Slide

  4. 1. Теория
    Введение
    О чём вообще пойдёт речь?

    View Slide

  5. Spring Security — это:
    ✓ Какая-то приблуда для безопасности
    ✓ Очередной фреймворк зоопарка Spring
    ✓ “Коробочное” решение для защиты
    приложений от рисков ИБ
    5
    Интуитивное представление: ОК ✔

    View Slide

  6. “Spring Security is a powerful
    and highly customizable
    authentication and access-control
    framework”
    6
    По мнению
    авторов
    Ни слова про
    light-weight

    View Slide

  7. Аутентификация
    Отвечает на вопрос:
    “Ты ли это?”
    Имеет дело с логинами
    и паролями.
    Устраняем любимую путаницу
    Авторизация
    Отвечает на вопрос:
    “Можно ли тебе сюда?”
    Имеет дело с правами,
    ролями, доступами...
    7
    Наша главная
    тема сегодня
    Но начнём
    с этой

    View Slide

  8. 1. Теория
    Авторизация
    Она же: контроль доступа

    View Slide

  9. Вместо disclaimer’а
    9
    ○ Пробежимся по верхушкам
    ○ Только для общего представления
    ○ Без примеров и конкретики

    View Slide

  10. Интерфейс AccessDecisionManager
    10
    public interface AccessDecisionManager {
    void decide(Authentication authentication, Object object,
    Collection configAttributes)
    throws AccessDeniedException, InsufficientAuthenticationException;
    boolean supports(ConfigAttribute attribute);
    boolean supports(Class> clazz);
    }

    View Slide

  11. Интерфейс AccessDecisionManager
    11
    ✢ Центральный компонент авторизации
    ✢ Опрашивает других участников выбора
    "пускать или нет"
    ✢ Обычно делегирует имплементациям
    интерфейса AccessDecisionVoter

    View Slide

  12. Интерфейс AccessDecisionVoter
    12
    public interface AccessDecisionVoter {
    int ACCESS_GRANTED = 1;
    int ACCESS_ABSTAIN = 0;
    int ACCESS_DENIED = -1;
    int vote(Authentication authentication, S object,
    Collection attributes);
    boolean supports(ConfigAttribute attribute);
    boolean supports(Class> clazz);
    }

    View Slide

  13. Авторизация в веб-приложениях
    13
    ✢ Включается через @EnableWebSecurity
    ✢ Работает как 1 фильтр FilterChainProxy
    ✢ Делегирует внутренним фильтрам (бинам)

    View Slide

  14. 14
    Фильтры Spring Security
    https://spring.io/guides/topicals/spring-security-architecture

    View Slide

  15. Фильтры собираются в цепочки
    15
    ✢ Цепочек может быть несколько
    ✢ На каждый запрос срабатывает только одна
    ✢ В spring-boot-starter-security из коробки 6 цепочек:
    ○ Для статики
    ○ Для ошибок, для ...
    ○ Для всего остального
    11 фильтров

    View Slide

  16. Цепочки фильтров Spring Security
    16
    https://spring.io/guides/topicals/spring-security-architecture

    View Slide

  17. А что-нибудь покруче?
    Есть кое-что...
    17

    View Slide

  18. Авторизация на уровне методов
    18
    ✢ Включается через аннотацию:
    @EnableGlobalMethodSecurity(securedEnabled=true)
    ✢ Работает как прокси (можно на AOP)
    ✢ При нарушении доступа выбрасывает:
    AccessDeniedException

    View Slide

  19. Варианты авторизации для методов
    19
    @Service
    public class MyService {
    @Secured("ROLE_USER")
    public String secure() {
    return "Hello Security";
    }
    }
    @PreAuthorize("hasRole('ADMIN')")
    @PostAuthorize("hasPermission(filterObject, 'read')")
    SpEL
    Но должно же у них быть
    что-то общее?

    View Slide

  20. 1. Теория
    Устройство
    Как это работает

    View Slide

  21. SecurityContext
    Краеугольный камень Spring Security.
    Содержит саму “аутентификацию”.
    21

    View Slide

  22. Интерфейс SecurityContext
    22
    public interface SecurityContext extends Serializable {
    Authentication getAuthentication();
    void setAuthentication(Authentication authentication);
    }
    Та самая “аутентификация”

    View Slide

  23. Интерфейс Authentication
    23
    public interface Authentication extends Principal, Serializable {
    Collection extends GrantedAuthority> getAuthorities();
    Object getCredentials();
    Object getDetails();
    Object getPrincipal();
    boolean isAuthenticated();
    void setAuthenticated(boolean isAuthenticated)
    throws IllegalArgumentException;
    }

    View Slide

  24. Что содержит Authentication
    24
    principal — это обычно пользователь
    (наследник UserDetails; у нас это карта)
    credentials — это обычно пароль (String)
    authorities — список разрешений/доступов
    details — что угодно (IP, свойства и т.п.)
    authenticated — признак успешной проверки

    View Slide

  25. SecurityContext доступен отовсюду
    25
    ✢ Напрямую через SecurityContextHolder:
    SecurityContext context = SecurityContextHolder.getContext();
    Authentication authentication = context.getAuthentication();
    assert authentication.isAuthenticated();
    ✢ Опосредованно через аннотации:
    @RequestMapping("/foo")
    public String foo(@AuthenticationPrincipal User user) {
    // do stuff with user
    }
    почти

    View Slide

  26. SecurityContext доступен отовсюду
    26
    ✢ Опосредованно из сервлет-контейнера:
    @RequestMapping("/foo")
    public String foo(Principal principal) {
    Authentication authentication = (Authentication) principal;
    User user = (User) authentication.getPrincipal();
    // do stuff with user
    }
    почти
    Но откуда он попадает
    во все эти места?

    View Slide

  27. “Spring Security is fundamentally thread bound
    because it needs to make
    the current authenticated principal available
    to a wide variety of downstream consumers”
    27
    По словам
    авторов

    View Slide

  28. “Fundamentally thread bound”
    28
    ✢ В каждом потоке свой SecurityContext
    ✢ Как правило, за нас это делает Spring Security
    ✢ Но иногда можно/нужно самим:
    @Configuration
    public class ApplicationConfiguration extends AsyncConfigurerSupport {
    @Override
    public Executor getAsyncExecutor() {
    return new DelegatingSecurityContextExecutorService(newFixedThreadPool(5));
    }
    }
    А как же реактивщина?

    View Slide

  29. Reactive Spring Security ⚛
    29
    ✢ ReactiveSecurityContextHolder
    ✢ Под капотом использует
    reactor.util.context.Context
    ✢ Для веб-приложений работает за счёт
    ReactorContextWebFilter
    ✢ Нуждается в @EnableWebFluxSecurity
    и @EnableReactiveMethodSecurity

    View Slide

  30. 1. Теория
    Аутентификация
    “Ты ли это?”

    View Slide

  31. Пара слов о менеджерах
    31

    View Slide

  32. Интерфейс AuthenticationManager
    32
    public interface AuthenticationManager {
    Authentication authenticate(Authentication authentication)
    throws AuthenticationException;
    }
    Является входной точкой во всю логику
    аутентификации Spring Security

    View Slide

  33. Варианты ответа метода authenticate()
    33
    ✢ Объект Authentication (authenticated=true)
    ⇒ Всё ОК ✅
    ✢ Исключение AuthenticationException
    ⇒ Пшёлвон ⛔
    ✢ null, просто null
    ⇒ Я не в курсе, спроси другого ‍♂

    View Slide

  34. Класс ProviderManager
    34
    ✢ Основная имплементация для
    AuthenticationManager’а
    ✢ Делегирует набору AuthenticationProvider’ов
    ✢ Швыряет ProviderNotFoundException,
    если не находит подходящего провайдера

    View Slide

  35. AuthenticationManager AuthenticationProvider
    35
    Вася
    Менеджер

    View Slide

  36. ProviderManager может иметь родителя
    36
    https://spring.io/guides/topicals/spring-security-architecture

    View Slide

  37. ProviderManager
    умеет рассылать
    события
    37

    View Slide

  38. Как создать AuthenticationManager’а
    38
    Способы:
    ✢ С помощью AuthenticationManagerBuilder ‍♂
    ✢ Вручную, с нуля
    Области:
    ✢ Глобально на всё приложение
    ✢ Локально на заданную часть

    View Slide

  39. Пример 1: локально, builder’ом
    39
    @Configuration
    public class ApplicationSecurity extends WebSecurityConfigurerAdapter {
    @Autowired
    DataSource dataSource;
    @Override
    public void configure(AuthenticationManagerBuilder builder) {
    builder.jdbcAuthentication().dataSource(dataSource)
    .withUser("dave").password("secret")
    .roles("USER");
    }
    }

    View Slide

  40. Пример 2: глобально, с нуля
    40
    @Bean
    public AuthenticationManager globalAuthenticationManager(
    PasswordAuthenticationProvider passwordAuthenticationProvider,
    PinAuthenticationProvider pinAuthenticationProvider) {
    var providerManager = new ProviderManager(List.of(
    passwordAuthenticationProvider,
    pinAuthenticationProvider));
    // всякие манипуляции с этим объектом
    return providerManager;
    }
    Перекроет бин, поставляемый
    spring-boot-starter-security

    View Slide

  41. Словарный запас Spring Security
    41
    ProviderManager
    AuthenticationManager
    AuthenticationProvider
    имплементирован
    делегирует
    подчинённый

    View Slide

  42. А что делать с учётками?
    Под интерфейс их!
    42

    View Slide

  43. Интерфейс UserDetailsService
    43
    public interface UserDetailsService {
    UserDetails loadUserByUsername(String username)
    throws UsernameNotFoundException;
    }
    Является "мостом" между прикладным
    хранилищем учётных данных и Spring Security

    View Slide

  44. Интерфейс UserDetailsService
    44
    Имеет реализации в Spring Security:
    ✢ JDBC
    ✢ In-memory
    ✢ Кэширующая прослойка
    ✢ …
    ✢ И легко запилить свою

    View Slide

  45. UserDetails
    Абстрагирует фреймворк
    от прикладных моделей пользователей
    45

    View Slide

  46. Интерфейс UserDetailsService
    46
    public interface UserDetails extends Serializable {
    Collection extends GrantedAuthority> getAuthorities();
    String getPassword();
    String getUsername();
    boolean isAccountNonExpired();
    boolean isAccountNonLocked();
    boolean isCredentialsNonExpired();
    boolean isEnabled();
    }
    * Есть реализация
    в Spring Security
    (класс User)

    View Slide

  47. Превратности контракта UserDetails
    47
    ✢ Метод getUserName() никогда не должен
    возвращать null.
    ✢ Метод getPassword() может вернуть null:
    ○ Критичные данные могут стираться из памяти
    после успешной аутентификации.
    ○ См. CredentialsContainer#eraseCredentials
    Кстати, о паролях...

    View Slide

  48. Интерфейс PasswordEncoder
    48
    public interface PasswordEncoder {
    String encode(CharSequence rawPassword);
    boolean matches(CharSequence rawPassword, String encodedPassword);
    }
    (Де)Кодирует пароли для безопасного хранения
    https://docs.spring.io/spring-security/site/docs/5.2.6.RELEASE/reference/htmlsingle/#core-services-password-encoding

    View Slide

  49. Какой алгоритм самый стойкий?
    В перспективе ‒ никакой!
    49

    View Slide

  50. DelegatingPasswordEncoder
    ✔ Учитывает современные требования ИБ
    ✔ Обеспечивает миграцию на новые
    алгоритмы
    ✔ Поддерживает старые приложения
    50

    View Slide

  51. Класс DelegatingPasswordEncoder
    51
    Хранит пароли в формате “{id}encodedPassword”:
    ✢ id ‒ идентификатор алгоритма
    ✢ encodedPassword ‒ кодированный пароль
    (может включать метаданные)

    View Slide

  52. Примеры хэшей от слова “password”
    52
    {bcrypt}$2a$10$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG
    {pbkdf2}5d923b44a6d129f3ddf3e3c8d29412723dcbde72445e8ef6bf3b508fbf17fa4ed4d6b99ca763d8dc
    {sha256}97cde38028ad898ebc02e690819fa220e88c62e0699403e94fff291cfffaf8410849f27605abcbc0
    {argon2}$argon2id$v=19$m=4096,t=3,p=1$PvvIwF0BSb/ycgO51cSkPg$xizQ/EyAyLYJb+/E+KiJf1bg5RUdcUUttly0bA6MjUU
    {noop}password

    View Slide

  53. Класс DelegatingPasswordEncoder
    53
    ✢ Используется в Spring Security по умолчанию
    ✢ Умеет “совершенствовать” хэши паролей
    ✢ Удобно создавать через
    PasswordEncoderFactories

    View Slide

  54. Алгоритмы хэширования паролей
    54
    SHA-1, SSHA (ldap), SHA-256, MD-5, MD-4
    Не безопасны, не рекомендованы, вызывают
    головную боль и предупреждения в IDE
    ➖ scrypt, bcrypt
    Широко распространённые варианты
    (не только в экосистеме JVM)
    pbkdf2, argon2
    Современные намеренно-ресурсоёмкие алгоритмы

    View Slide

  55. Алгоритм Argon2 в Spring Security
    55
    ✢ Реализован в org.bouncycastle:bcprov-jdk15on:1.64
    ✢ Используется через класс Argon2PasswordEncoder
    ✢ Генерирует соль из SecureRandom
    ⇒ один пароль всякий раз даёт разные хэши

    View Slide

  56. Argon2 BCrypt
    56 https://virgo.ftc.ru/x/YYwDOQ

    View Slide

  57. 1. Теория
    Заключение
    Резюме и выводы

    View Slide

  58. Кратко о Spring Security в целом
    58
    ✢ Помогает с аутентификацией и авторизацией
    ✢ Обеспечивает гибкость через интерфейсы
    ✢ Состоит из модулей (core, web, config, ldap, ...)

    View Slide

  59. Резюме по авторизации
    59
    ✢ Работает в веб-приложениях за счёт фильтров
    ✢ Умеет защищать методы через прокси-обёртки
    ✢ Основные классы:
    ○ @EnableWebSecurity, @EnableGlobalMethodSecurity
    ○ AccessDecisionManager, AccessDecisionVoter
    ○ @PreAuthorize, @PostAuthorize

    View Slide

  60. Резюме по аутентификации
    60
    ✢ Является “скелетом” для подключения разных
    механизмов проверки
    ✢ Предоставляет средства работы с паролями
    ✢ Основные классы:
    ○ Authentication, AuthenticationManager
    ○ SecurityContext, SecurityContextHolder
    ○ UserDetails, UserDetailsService

    View Slide

  61. Остальное
    здесь
    ✢ Описание
    ✢ Sequences
    ✢ Подсказки
    ✢ Дроплеты
    ✢ ...
    61
    https://virgo.ftc.ru/x/YYwDOQ

    View Slide

  62. 62

    View Slide

  63. 2. Применение
    Как всё это выглядит на деле

    View Slide

  64. Show me the code!
    64

    View Slide

  65. Спасибо!
    Вопросы?
    Материалы будут разосланы
    отдельным письмом
    65

    View Slide

  66. Credits
    Special thanks to all the people who made and
    released these awesome resources for free:
    ✢ Presentation template by SlidesCarnival
    ✢ Photographs by Unsplash
    66

    View Slide