какая аннотация включает защиту на уровне методов в spring security
Подготовка к Spring Professional Certification. Spring Security
Эта статья является переводом статьи по подготовке к Spring Professional Certification.
В ней будет рассмотрена тема Spring Security и основные вопросы по ней.
Ее также можно использовать для подготовки к собеседованию.
↓ Остальные статьи доступны по ссылкам в оглавлении ↓
Аутентификация — процесс верификации пользователя компьютерной системы.
Вот как он происходит в Spring:
Авторизация — это процесс удостоверения в том, что у пользователя есть роль, требуемая чтобы сделать какое-либо действие. При авторизации проверяется, есть ли у вас соответствующие права на доступ к ресурсу.
Сначала происходит аутентификация, а потом — авторизация.
Используя Spring AOP proxy, которые наследуются от класса AbstractSecurityInterceptor.
Применяется для методов вызывающих авторизацию.
Веб-инфраструктура в Security основана на servlet-фильтрах.
SeccurityFilterChain сравнивает URL в запросе со списком фильтров.
SecurityContextHolder — содержит и предоставляет доступ к SecurityContext в приложении.
SecurityContext — дефолтная реализация Spring Security содержащая объект Authentication.
Authentication — предоставляет токен для запроса аутентификации или для принципала, который прошел аутентификацию. Также содержит список полномочий, к которым получил доступ принципал.
GrantedAuthority — содержит полномочия выданные прошедшему проверку принципалу.
UserDetails — содержит информацию о пользователе: пароль, логин, полномочия. Эта информация используется для создания объекта Authentication после удачной аутентификации.
UserDetailsService — этот сервис извлекает информацию о пользователе из хранилища(память программы, бд, и т.п.) и кладет ее в UserDetails.
Это специальный фильтр, который делегирует работу другим бинам, которые также являются фильтрами.
Конструктор DSFC принимает несколько параметров. Первый параметр — request matcher. Остальные параметры — это фильтры, реализующие интерфейс servlet.Filter. Вот все фильтры, принимаемые DSFC:
Authentication представляет следующие свойства:
Это выражение означает “любой”.
* — перехватывает только на том уровне, на котором используется.
Например, паттерн “/orders/*” проверит права пользователя, если пользователь перейдет по
/orders/aliens или /orders/1, но не /orders/alien/1.
** — перехватывает на всех уровнях.
Будут проверены любые запросы, /orders/aliens, /orders/1, /orders/alien/1.
Соль используется для вычисления хеш-значения пароля. Это последовательность рандомных чисел, которые используются для преобразования текстового пароля в хеш. Соль хранится в открытом виде рядом с хеш-паролем и может использоваться в дальнейшем при конвертации чистого пароля в хеш при новом логине пользователя.
Spring Security поддерживает защиту отдельных методов в бинах(например, в контроллерах). Это дополнительный слой защиты для приложения.
Эта аннотация основана на JSR-250.
@RolesAllowed позволяет настроить доступ к методам(например, в классе-контроллере) с помощью ролей.
Пример: @RolesAllowed(“ADMIN”) будет пропускать только пользователей с ролью ADMIN
Для использования нужно установить @EnableGlobalMethodSecurity(jsr250Enabled=true) на @Configuration классе + нужно чтобы эта аннотация была в classpath.
@PreAuthorize позволяет настроить доступ к методу используя SpEL.
Для использования нужно установить @EnableGlobalMethodSecurity(prePostEnabled=true)
Используется сквозная функциональность, с помощью Spring AOP(прокси-объекты).
Введение в безопасность методов Spring
Введение в безопасность методов Spring
1. Вступление
Проще говоря, Spring Security поддерживает семантику авторизации на уровне метода.
В этой статье мы сначала рассмотрим использование некоторых аннотаций по безопасности. Затем мы сосредоточимся на тестировании безопасности нашего метода с помощью различных стратегий.
2. Включение безопасности метода
Прежде всего, чтобы использовать Spring Method Security, нам нужно добавить зависимостьspring-security-config:
Его последнюю версию можно найти наMaven Central.
Если мы хотим использовать Spring Boot, мы можем использовать зависимостьspring-boot-starter-security, которая включаетspring-security-config:
Опять же, последнюю версию можно найти наMaven Central.
Далее нам нужно включить глобальную безопасность метода:
СвойствоprePostEnabled включает аннотации до и после публикации Spring Security.
СвойствоsecuredEnabled определяет, должна ли быть включена аннотация@Secured
Свойствоjsr250Enabled позволяет нам использовать аннотацию@RoleAllowed
Подробнее об этих аннотациях мы поговорим в следующем разделе.
3. Применение безопасности метода
3.1. Использование аннотации@Secured
The @Secured annotation is used to specify a list of roles on a method. Следовательно, пользователь может получить доступ к этому методу, только если у него есть хотя бы одна из указанных ролей.
Здесь аннотация@Secured(“ROLE_VIEWER”) определяет, что только пользователи с рольюROLE_VIEWER могут выполнять методgetUsername.
Кроме того, мы можем определить список ролей в аннотации@Secured:
В этом случае конфигурация указывает, что если у пользователя естьROLE_VIEWER илиROLE_EDITOR, этот пользователь может вызвать методisValidUsername.
Аннотация@Secured не поддерживает Spring Expression Language (SpEL).
3.2. Использование аннотации@RoleAllowed
По сути, мы можем использовать аннотацию@RoleAllowed так же, как@Secured. Таким образом, мы можем переопределить методыgetUsername иisValidUsername:
Точно так же только пользователь с рольюROLE_VIEWER может выполнятьgetUsername2.
Опять же, пользователь может вызыватьisValidUsername2, только если у него есть хотя бы одна из ролейROLE_VIEWER илиROLER_EDITOR.
3.3. Использование аннотаций@PreAuthorize и@PostAuthorize
Both @PreAuthorize and @PostAuthorize annotations provide expression-based access control. Следовательно, предикаты могут быть записаны с использованиемSpEL (Spring Expression Language).
The @PreAuthorize annotation checks the given expression before entering the method, тогда какthe @PostAuthorize annotation verifies it after the execution of the method and could alter the result.
Теперь давайте объявим методgetUsernameInUpperCase, как показано ниже:
@PreAuthorize(“hasRole(‘ROLE_VIEWER’)”) имеет то же значение, что и@Secured(“ROLE_VIEWER”), которое мы использовали в предыдущем разделе. Не стесняйтесь открывать для себя большеsecurity expressions details in previous articles.
Следовательно, аннотацию@Secured(\<“ROLE_VIEWER”,”ROLE_EDITOR”>) можно заменить на@PreAuthorize(“hasRole(‘ROLE_VIEWER’) or hasRole(‘ROLE_EDITOR’)”):
Кроме того,we can actually use the method argument as part of the expression:
Здесь пользователь может вызвать методgetMyRoles, только если значение аргументаusername совпадает с именем пользователя текущего принципала.
It’s worth to note that @PreAuthorize expressions can be replaced by @PostAuthorize ones.
В предыдущем примере, однако, авторизация будет задерживаться после выполнения целевого метода.
Дополнительноthe @PostAuthorize annotation provides the ability to access the method result:
В этом примере методloadUserDetail будет успешно выполняться, только еслиusername возвращаемогоCustomUser равноnickname. текущего участника аутентификации.
В этом разделе мы в основном используем простые выражения Spring. Для более сложных сценариев мы могли бы создатьcustom security expressions.
3.4. Использование аннотаций@PreFilter и@PostFilter
Spring Security provides the @PreFilter annotation to filter a collection argument before executing the method:
В этом примере мы объединяем все имена пользователей, кроме того, который прошел аутентификацию.
Здесьour expression uses the name filterObject to represent the current object in the collection.
Однако, если метод имеет более одного аргумента, который является типом коллекции, нам нужно использовать свойствоfilterTarget, чтобы указать, какой аргумент мы хотим фильтровать:
Дополнительноwe can also filter the returned collection of a method by using @PostFilter annotation:
В этом случае имяfilterObject относится к текущему объекту в возвращаемой коллекции.
С этой конфигурацией Spring Security будет перебирать возвращенный список и удалять любое значение, которое соответствует имени пользователя участника.
Более подробную информацию о@PreFilter и@PostFilter можно найти в статьеSpring Security – @PreFilter and @PostFilter.
3.5. Мета-аннотация безопасности метода
Обычно мы находимся в ситуации, когда мы защищаем разные методы, используя одну и ту же конфигурацию безопасности.
В этом случае мы можем определить метааннотацию безопасности:
Далее мы можем напрямую использовать аннотацию @IsViewer для защиты нашего метода:
3.6. Аннотация безопасности на уровне класса
Если мы обнаружим, что используем одну и ту же аннотацию безопасности для каждого метода в пределах одного класса, мы можем рассмотреть возможность размещения этой аннотации на уровне класса:
В приведенном выше примере правило безопасностиhasRole(‘ROLE_ADMIN’) будет применяться к методамgetSystemYear иgetSystemDate.
3.7. Множественные аннотации безопасности к методу
Мы также можем использовать несколько аннотаций безопасности для одного метода:
Следовательно, Spring будет проверять авторизацию как до, так и после выполнения методаsecuredLoadUserDetail.
4. Важные соображения
Мы хотели бы напомнить о двух моментах, касающихся безопасности метода:
By default, Spring AOP proxying is used to apply method security –, если защищенный метод A вызывается другим методом в том же классе, безопасность в A полностью игнорируется. Это означает, что метод A будет выполняться без какой-либо проверки безопасности. То же самое относится и к частным методам
Spring SecurityContext is thread-bound – по умолчанию, контекст безопасности не распространяется на дочерние потоки. Для получения дополнительной информации мы можем обратиться к статьеSpring Security Context Propagation
5. Безопасность метода тестирования
5.1. конфигурация
Чтобы протестировать Spring Security с помощью JUnit, нам нужна зависимостьspring-security-test:
Нам не нужно указывать версию зависимости, потому что мы используем плагин Spring Boot. Последние версии этой зависимости можно найти наMaven Central.
Затем давайте настроим простой тест Spring Integration, указав бегуна и конфигурациюApplicationContext:
5.2. Тестирование имени пользователя и ролей
Теперь, когда наша конфигурация готова, давайте попробуем протестировать наш методgetUsername, который защищен аннотацией@Secured(“ROLE_VIEWER”):
Поскольку здесь мы используем аннотацию@Secured, для вызова метода требуется, чтобы пользователь прошел аутентификацию. В противном случае мы получимAuthenticationCredentialsNotFoundException.
Следовательно,we need to provide a user to test our secured method. To achieve this, we decorate the test method with @WithMockUser and provide a user and roles:
Обратите внимание, что здесь нет необходимости добавлять префиксROLE_, Spring Security добавит этот префикс автоматически.
Если мы не хотим иметь этот префикс, мы можем рассмотреть возможность использованияauthority вместоrole..
Например, давайте объявим методgetUsernameInLowerCase:
Мы могли бы проверить это, используя полномочия:
Удобно,if we want to use the same user for many test cases, we can declare the @WithMockUser annotation at test class:
Если бы мы хотели запустить наш тест как анонимный пользователь, мы могли бы использовать аннотацию@WithAnonymousUser:
В приведенном выше примере мы ожидаемAccessDeniedException, потому что анонимному пользователю не предоставлена рольROLE_VIEWER или полномочияSYS_ADMIN.
5.3. Тестирование с пользовательскимUserDetailsService
For most applications, it’s common to use a custom class as authentication principal. В этом случае настраиваемый класс должен реализовать интерфейсorg.springframework.security.core.userdetails.UserDetails.
В этой статье мы объявляем классCustomUser, который расширяет существующую реализациюUserDetails, то естьorg.springframework.security.core.userdetails.User:
Вернемся к примеру с аннотацией@PostAuthorize из раздела 3:
В этом случае метод будет успешно выполняться только в том случае, еслиusername возвращенногоCustomUser равноnickname текущего участника аутентификации.
Если бы мы хотели протестировать этот метод, we could provide an implementation of UserDetailsService which could load our CustomUser based on the username:
В аннотации@WithUserDetails указано, что мы будем использоватьUserDetailsService для инициализации аутентифицированного пользователя. На сервис ссылается свойствоuserDetailsServiceBeanName.. ЭтотUserDetailsService может быть реальной реализацией или подделкой для целей тестирования.
Кроме того, служба будет использовать значение свойстваvalue в качестве имени пользователя для загрузкиUserDetails.
Для удобства мы также можем украсить аннотацией@WithUserDetails на уровне класса, аналогично тому, что мы сделали с аннотацией@WithMockUser.
5.4. Тестирование с метааннотациями
Мы часто обнаруживаем, что снова и снова используем одного и того же пользователя / роли в различных тестах.
Для этих ситуаций удобно создатьmeta-annotation.
Возвращаясь к предыдущему примеру@WithMockUser(username=”john”, roles=\<“VIEWER”>), мы можем объявить метааннотацию как:
Тогда мы можем просто использовать@WithMockJohnViewer в нашем тесте:
Точно так же мы можем использовать метааннотации для создания пользователей, зависящих от домена, используя@WithUserDetails.
6. Заключение
В этом руководстве мы изучили различные варианты использования Method Security в Spring Security.
Мы также прошли несколько методик, чтобы легко протестировать безопасность методов и узнали, как повторно использовать поддельных пользователей в различных тестах.
Все примеры этого руководства можно найтиover on Github.
Краткий обзор Spring Security
Итак, дорогой хабраюзер, предлагаю тебе рассмотреть такие аспекты Spring Security как:
Ключевые объекты контекста Spring Security:
Позволяет получить из источника данных объект пользователя и сформировать из него объект UserDetails который будет использоваться контекстом Spring Security.
Аутентификация
(1) Пользователю будет предложено войти в систему предоставив имя (логин или email) и пароль. Имя пользователя и пароль объединяются в экземпляр класса UsernamePasswordAuthenticationToken(экземпляр интерфейса Authentication) после чего он передается экземпляру AuthenticationManager для проверки.
(2) В случае если пароль не соответствует имени пользователя будет выброшено исключение BadCredentialsException с сообщением “Bad Credentials”.
(3) Если аутентификация прошла успешно возвращает полностью заполненный экземпляр Authentication.
(4) Для пользователя устанавливается контекст безопасности путем вызова метода SecurityContextHolder.getContext().setAuthentication(…), куда передается объект который вернул AuthenticationManager.
Подключение поддержки Security для SpringFramework приложения:
Ну и конечно же сам файл с настройкой security.xml
Пояснение к коду security.xml:
Подразумевается что на странице login.jsp есть форма с action=»/j_spring_security_check» в которой содержаться input’ы для имени и пароля с name=«j_username» и name=«j_password», а также checkbox c name=»_spring_security_remember_me». Это всё специальные значения которые требует Spring Security иначе параметры просто не будут передаваться в контекст безопасности. После успешного прохождения аутентификации пользователь будет перенаправлен на страницу /index где уже применяются правила авторизации. Если не указывать форму и url в http spring-security тогда по умолчанию будет работать basic authentication или можно подключить basic authentication насильно указав в http spring-security
На url /index* доступ могут иметь пользователи с правами ROLE_USER, а также гости (все подключения которые не прошли аутентификацию получают имя guest и права ROLE_ANONYMOUS).
Доступ к url /add* имеют только пользователи с правами ROLE_USER Доступ к url /delete* только пользователи с правами ROLE_ADMIN
Также, авторизованный доступ можно прикручивать на методы, для этого в security.xml нужно добавить, следующий элемент:
Также может осуществляться проверка хешированных паролей:
Java и сопутствующие товары
пятница, 24 июня 2016 г.
Spring Security. Простая конфигурация
При разработке вэб приложения рано или поздно необходимо решать задачу безопасности. В этом вопросе Spring Security предоставляет комплексные решения безопасности, аутентификации и авторизации. Построенный на основе Spring Framework, Spring Security имеет все преимущества Dependecy Injection и AOP
Конфигурация Spring Security начинается со следующих моментов:
Важно обратить внимание на
Сама конфигурация происходит через переопределение одного из методов configure:
Вот пример самой простой конфигурации (через http basic):
Этот пример нам говорит о том, что все http запросы к нашему приложению должны быть аутентифицированы(authorizeRequests().anyRequest().authenticated()) и логин происходит через преконфигуренную логин форму и логин страницу(formLogin()).
Самый простой способо воспользоваться «in-memory» хранищем:
Можно провести аутентификацию через базу данных:
Конфигурем логин пейджу
Если кроме юзеров и ролей вам нужно еще выбрать пермишены и у вас более сложная настройко, то удобно делать конфигурацию через UserDetailsService. Для этого нам нужно реализовать интрефейс с одним методом, который должен вернуть объект типа UserDetails:
В моем примере это выглядит так:
Это все базовые моменты, которые касаются конфигурацией на уровне web. Дальше рассмотрим секьюрити на уровне методов. Базовые настройки:
Мы исользуем аннотацию(1) @EnableGlobalMethodSecurity чтобы секьюрити через методы стало доступным. Указываем какого именно типа аннотоция должна стать доступна. В данном случае @PreAuthorize. Можно использовать следуюшие типы аннотаций:
На мой взгяд это удобно для рест сервиса, а для обычного веб приложения хватит обычное web аутентификация. В целом фреймворк очень удобный как с точки зрения быстрой настройки секьюрити, так и с точки зрения более продвинутых фич. Вот мой код с двумя модулями: initial (без секьюрити) и base-security(защищенное)
Spring Security/Технический обзор Spring Security
Эта статья представляет собой перевод Spring Security Reference Documentation, Ben Alex, Luke Taylor 3.0.2.RELEASE, Глава 5, Технический обзор.
Содержание
Среда исполнения [ править ]
Для Spring Security 3.0 требуется среда исполнения Java 5.0 или выше. Т.к. Spring Security стремится работать автономно, то нет никакой необходимости размещать специальные файлы-конфигурации в Java Runtime Environment. В частности, нет необходимости специально настраивать файл политики Java Authentication and Authorization Service (JAAS) или помещать Spring Security в общий CLASSPATH.
Аналогичным образом, если вы используете EJB контейнер или контейнер сервлета, то нет необходимости создавать где-либо специальные конфигурационные файлы или включать Spring Security в загрузчик классов сервера. Все необходимые файлы будут содержаться в вашем приложении.
Такая конструкция обеспечивает максимальную гибкость во время развертывания, так как вы можете просто скопировать целевой артефакт (JAR, WAR или EAR) из одной системы в другую, и он будет работать.
Ключевые компоненты [ править ]
В Spring Security 3.0, содержимое jar-файла spring-security-core было урезано до минимума. Он не содержит никакого кода, связанного с безопасностью веб-приложений, LDAP или конфигурирования с помощью пространства имен. Здесь мы рассмотрим некоторые Java типы, которые можно найти в основном модуле. Они представляют собой строительные блоки каркаса. Так что если вам когда-нибудь понадобится выйти за рамки простой конфигурации пространства имен, то важно чтобы вы понимали что они собой представляют, даже если вам не потребуется взаимодействовать с ними напрямую.
Объекты SecurityContextHolder, SecurityContext и Authentication [ править ]
Получение информации о текущем пользователе [ править ]
Внутри SecurityContextHolder мы храним информацию о доверителе, взаимодействующим в настоящее время с приложением. Spring Security использует объект Authentication для представления этой информации. Как правило нет необходимости создавать объект Authentication самостоятельно, но запросы к объекту Authentication довольно распространенное действие. Вы можете использовать следующий код в любом месте вашего приложения, чтобы получить имя текущего зарегистрированного пользователя, например:
Сервис UserDetails [ править ]
Это наиболее общий подход к загрузке информации о пользователе в Spring Security и вы увидите, что это используется в каркасе когда требуется информация о пользователе.
GrantedAuthority [ править ]
Резюме [ править ]
Просто напомним, основными блоками Spring Security являются:
Теперь, когда у вас есть понимание многократно используемых компонентов, давайте внимательнее рассмотрим на процесс аутентификации.
Аутентификация [ править ]
Spring Security можно использовать в самых разных средах аутентификации. Хотя мы рекомендуем использовать Spring Security для аутентификации, а не интегрировать ее с существующей Container Managed Authentication, хотя этот механизм и поддерживается. То же касается и интеграции с вашей собственной системой аутентификации.
Что представляет собой аутентификация в Spring Security [ править ]
Рассмотрим стандартный сценарий аутентификации с которым все хорошо знакомы.
Пользователь перенаправляется на выполнение операций, которые могут быть защищены механизмом контроля доступа, который проверяет необходимые разрешения для выполнения операций на основании информации текущего контекста безопасности.
Первые три пункта составляют непосредственно процесс аутентификации, поэтому мы рассмотрим, как это происходит в Spring Security.
С этого момента пользователь считается подлинным. Давайте рассмотрим код в качестве примера.
Установка содержимого SecurityContextHolder напрямую [ править ]
Аутентификация в Веб-приложениях [ править ]
Теперь давайте исследуем ситуацию, где вы используете Spring Security в веб-приложении (система безопасности в web.xml выключена). Как аутентифицируется пользователь и устанавливается контекст безопасности приложения?
Рассмотрим типичный процесс аутентификации веб-приложения
ExceptionTranslationFilter [ править ]
AuthenticationEntryPoint [ править ]
Механизм аутентификации [ править ]
Сохранение SecurityContext между запросами [ править ]
Многие другие типы приложений(например, RESTful веб-сервисы без сохранения состояния) не используют HTTP сессии и будут требовать аутентификации при каждом запросе. Тем не менее, все равно очень важно, чтобы SecurityContextPersistenceFilter входил в цепочку, чтобы SecurityContextHolder очищался после каждого запроса.
Управление доступом (Авторизация) в Spring Security [ править ]
Безопасность и Советы AOP [ править ]
Если вы хорошо знакомы с AOP, то должны знать что существуют различные виды советов: before, after, throws и around. Совет around очень полезен, потому что советчик может выбирать, следует или нет осуществить вызов метода, следует или нет изменить отклик, следует или нет пробросить исключение. Spring Security предоставляет around советы как для вызова методов, так и для веб-запросов. Для вызова методов совет around реализуется с помощью стандартного AOP модуля Spring’а, а для веб-запросов с помощью стандартного фильтра.
Для тех, кто не знаком с AOP, главное понять, что Spring Security может защищать вызовы методов так же хорошо, как и веб-запросы. Для большинства людей важно обеспечить безопасность вызова методов на уровне сервисов. Потому что на уровне сервисов сосредоточено большинство бизнес-логики нынешнего поколения J2EE приложений. Если вам просто нужно обеспечить безопасность при вызове методов на уровне сервисов, то стандартный Spring AOP будет весьма уместным. Если вам нужно обеспечить безопасность непосредственно объектов предметной области, то вероятно следует рассмотреть вариант использования AspectJ.
Защищенные Объекты и AbstractSecurityInterceptor [ править ]
Что такое «защищенный объект» в общем смысле? Spring Security использует этот термин для обозначения любого объекта, к которому могут применяться механизмы обеспечения безопасности (например, авторизация). Наиболее распространенными примерами являются вызовы методов и веб-запросы.
AbstractSecurityInterceptor обеспечивает последовательный рабочий процесс для обработки запросов к защищенному объекту, обычно:
Что такое конфигурационные атрибуты [ править ]
RunAsManager [ править ]
AfterInvocationManager [ править ]
AbstractSecurityInterceptor и связанные с ним объекты показаны на рисунке 5.1, «Модель перехватчиков системы безопасности и «защищенного объекта».
Расширение модели защищенного объекта [ править ]
Только те разработчики, которые рассматривают возможность создания полностью нового способа перехвата и авторизации запросов, должны напрямую использовать защищенные объекты. Например, можно было бы построить новый защищенный объект для системы обмена сообщениями. Все что требует обеспечения безопасности и обеспечивает способ перехвата вызовов (на подобие семантики AOP совета around) может быть превращено в защищенный объект. Можно сказать, что в большинстве Spring-приложений можно легко и прозрачно использовать три, в настоящее время поддержаващихся, типа защищенных объектов (MethodInvocation AOP альянса, AspectJ JoinPoint и FilterInvocation для веб-запросов).
Локализация [ править ]
Spring Security поддерживает локализацию сообщений в исключениях, которые скорее всего увидят конечные пользователи. Если ваше приложение разработано для Англоговорящих пользователей, то по умолчанию вы не должны ничего делать, все сообщения Spring Security написаны на английском языке. Если вы должны поддерживать локализацию для других языков, то все что вам нужно знать, содержится в этом разделе.
Все сообщения исключений могут быть локализованы, включая сообщения, связанные с отказом аутентификации и запрета доступа (отказы авторизации). Исключения и логи, которые предназначены для разработчиков или лиц, ответственных за развертывание приложения (включая некорректные атрибуты, нарушения контракта интерфейса, использование некорректных конструкторов, проверки во время запуска, логгирование режима отладки) и т.д., не локализуются, а вместо этого явно написаны в коде Spring Security на английском языке.