Введение в Spring Security Expressions

Введение в 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.