Введение в Spring Security Expressions
1. Вступление
В этом руководстве мы сосредоточимся на выражениях безопасности Spring и, конечно же, на практических примерах с этими выражениями.
Прежде чем рассматривать более сложные реализации (такие как ACL), важно иметь четкое представление о выражениях безопасности, поскольку они могут быть довольно гибкими и мощными при правильном использовании.
Эта статья является расширениемSpring Security Expressions – hasRole Example.
2. Maven Зависимости
Чтобы использовать Spring Security, вам необходимо включить следующий раздел в ваш файлpom.xml:
org.springframework.security
spring-security-web
4.1.1.RELEASE
Последнюю версию можно найтиhere.
И небольшое примечание - эта зависимость распространяется только на Spring Security; не забудьте добавить spring-core иspring-context для полноценного веб-приложения.
3. конфигурация
Во-первых, давайте взглянем на конфигурацию Java.
Мы расширимWebSecurityConfigurerAdapter, чтобы у нас была возможность подключиться к любой из точек расширения, которые предлагает базовый класс:
@Configuration
@EnableAutoConfiguration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityWithoutCsrfConfig extends WebSecurityConfigurerAdapter {
...
}
Конечно, мы можем также выполнить настройку XML:
4. Выражения веб-безопасности
Теперь давайте посмотрим на выражения безопасности:
-
Хасроле, Хасаниролл
-
Hasauthority, Hasanyauthority
-
Permitall, Denyall
-
Isanonymous, Isrememberme, Аутентифицированный, Isfully Аутентифицированный
-
Принципал, Аутентификация
-
hasPermission
А теперь давайте подробно рассмотрим каждый из них.
4.1. hasRole, hasAnyRoleс
Эти выражения отвечают за определение контроля доступа или авторизации для определенных URL-адресов или методов в вашем приложении.
Давайте посмотрим на пример:
@Override
protected void configure(final HttpSecurity http) throws Exception {
...
.antMatchers("/auth/admin/*").hasRole("ADMIN")
.antMatchers("/auth/*").hasAnyRole("ADMIN","USER")
...
}
В этом примере мы указываем доступ ко всем ссылкам, начинающимся с/auth/, только для пользователей, которые вошли в систему с рольюUSER или рольюADMIN.. Кроме того, для доступа к ссылкам, начинающимся с/auth/admin/, мы должен иметь рольADMIN в системе.
Та же конфигурация может быть достигнута в файле XML, написав:
4.2. hasAuthority, hasAnyAuthorityс
Роли и авторитеты схожи по весне.
Основное отличие состоит в том, что роли имеют особую семантику - начиная с Spring Security 4, префикс «ROLE_» автоматически добавляется (если его еще нет) любым методом, связанным с ролями.
Таким образом,hasAuthority(‘ROLE_ADMIN') похож наhasRole(‘ADMIN'), потому что префикс «ROLE_» добавляется автоматически.
Но преимущество использования авторитетных данных заключается в том, что нам вообще не нужно использовать префиксROLE_.
Вот краткий пример, в котором мы определяем пользователей с определенными полномочиями:
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("user1").password("user1Pass")
.authorities("USER")
.and().withUser("admin").password("adminPass")
.authorities("ADMIN");
}
Тогда мы, конечно, можем использовать следующие выражения полномочий:
@Override
protected void configure(final HttpSecurity http) throws Exception {
...
.antMatchers("/auth/admin/*").hasAuthority("ADMIN")
.antMatchers("/auth/*").hasAnyAuthority("ADMIN", "USER")
...
}
Как видим - здесь мы вообще не упоминаем роли.
Наконец, мы можем достичь той же функциональности, используя и конфигурацию XML:
And:
4.3. permitAll, denyAllс
Эти две аннотации также довольно просты. Мы можем разрешить доступ к некоторым URL-адресам в нашем сервисе или можем запретить доступ.
Давайте посмотрим на пример:
...
.antMatchers("/*").permitAll()
...
С помощью этой конфигурации мы разрешим всем пользователям (как анонимным, так и вошедшим в систему) доступ к странице, начинающейся с ‘/ '(например, нашей домашней страницы).
Мы также можем запретить доступ ко всему нашему URL-пространству:
...
.antMatchers("/*").denyAll()
...
И снова, та же самая конфигурация может быть сделана с конфигурацией XML также:
4.4. isAnonymous, isRememberMe, isAuthenticated, isFullyAuthenticatedс
В этом подразделе мы сосредоточимся на выражениях, относящихся к статусу входа пользователя. Начнем с пользователя, который не авторизовался на нашей странице. Указывая следующее в конфигурации Java, мы разрешаем всем неавторизованным пользователям доступ к нашей главной странице:
...
.antMatchers("/*").anonymous()
...
То же самое в конфиге XML:
Если мы хотим защитить веб-сайт, чтобы все, кто его использует, должны были войти в систему, нам нужно использовать методisAuthenticated():
...
.antMatchers("/*").authenticated()
...
или версия XML:
Кроме того, у нас есть два дополнительных выражения:isRememberMe() иisFullyAuthenticated(). Благодаря использованию cookie-файлов Spring предоставляет возможность запомнить меня, поэтому нет необходимости каждый раз входить в систему. Вы можете прочитатьmore about Remember Me here.
Чтобы предоставить доступ пользователям, которые вошли в систему только с помощью функции Запомнить меня, мы можем использовать это:
...
.antMatchers("/*").rememberMe()
...
или версия XML:
Наконец, некоторые части наших служб требуют повторной аутентификации пользователя, даже если пользователь уже вошел в систему. Например, пользователь хочет изменить настройки или платежную информацию; Конечно, рекомендуется запрашивать аутентификацию вручную в более чувствительных областях системы.
Для этого мы можем указатьisFullyAuthenticated(), который возвращаетtrue, если пользователь не является анонимным или запоминающим пользователем:
...
.antMatchers("/*").fullyAuthenticated()
...
или версия XML:
4.5. principal, authenticationс
Эти выражения позволяют получить доступ к объектуprincipal, представляющему текущего авторизованного (или анонимного) пользователя, и текущий объектAuthentication изSecurityContext соответственно.
Мы можем, например, использоватьprincipal для загрузки электронной почты, аватара пользователя или любых других данных, которые доступны для вошедшего в систему пользователя.
Аauthentication предоставляет информацию о полном объектеAuthentication вместе с предоставленными ему полномочиями.
Оба они описаны более подробно в следующей статье:Retrieve User Information in Spring Security.
4.6. hasPermission API
Это выражениеdocumented и предназначено для соединения системы выражений и системы ACL Spring Security, что позволяет нам указывать ограничения авторизации для отдельных объектов домена на основе абстрактных разрешений.
Давайте посмотрим на пример. У нас есть сервис, который позволяет совместно писать статьи с главным редактором, который решает, какую статью предложить другим авторам.
Чтобы разрешить использование такого сервиса, мы можем создать следующие методы с методами контроля доступа:
@PreAuthorize("hasPermission(#articleId, 'isEditor')")
public void acceptArticle(Article article) {
…
}
Только авторизованный пользователь может вызывать этот метод, а также пользователю необходимо иметь разрешениеisEditor в службе.
Нам также нужно не забыть явно настроитьPermissionEvaluator в контексте нашего приложения:
гдеcustomInterfaceImplementation будет классом, реализующимPermissionEvaluator.
Конечно, мы можем сделать это и с помощью конфигурации Java:
@Override
protected MethodSecurityExpressionHandler expressionHandler() {
DefaultMethodSecurityExpressionHandler expressionHandler =
new DefaultMethodSecurityExpressionHandler();
expressionHandler.setPermissionEvaluator(new CustomInterfaceImplementation());
return expressionHandler;
}
5. Заключение
Это руководство представляет собой всеобъемлющее введение и руководство по выражениям безопасности Spring.
Все обсуждаемые здесь примеры доступныon the GitHub project.