Einführung in Spring Security Expressions

1. Einleitung

In diesem Tutorial konzentrieren wir uns auf Spring Security Expressions und natürlich auf praktische Beispiele mit diesen Ausdrücken.

Bevor Sie sich komplexere Implementierungen (wie z. B. ACL) ansehen, ist es wichtig, die Sicherheitsausdrücke genau zu verstehen, da sie bei korrekter Verwendung sehr flexibel und leistungsstark sein können.

Dieser Artikel ist eine Erweiterung von Spring Security Expressions - hasRole Example.

2. Maven-Abhängigkeiten

Um Spring Security verwenden zu können, müssen Sie den folgenden Abschnitt in Ihre pom.xml- Datei aufnehmen:

  org.springframework.security spring-security-web 5.2.3.RELEASE  

Die neueste Version finden Sie hier.

Und ein kurzer Hinweis: Diese Abhängigkeit deckt nur Spring Security ab. Vergessen Sie nicht, s pring-core und spring-context für eine vollständige Webanwendung hinzuzufügen .

3. Konfiguration

Schauen wir uns zunächst eine Java-Konfiguration an.

Wir werden WebSecurityConfigurerAdapter erweitern, sodass wir die Option haben, sich an einen der Erweiterungspunkte anzuschließen , die die Basisklasse bietet:

@Configuration @EnableAutoConfiguration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) public class SecurityJavaConfig extends WebSecurityConfigurerAdapter { ... }

Natürlich können wir auch eine XML-Konfiguration vornehmen:

4. Web Security-Ausdrücke

Schauen wir uns nun die Sicherheitsausdrücke an:

  • hasRole , hasAnyRole
  • hasAuthority , hasAnyAuthority
  • allowAll , leugnenAll
  • isAnonymous , isRememberMe , isAuthenticated , isFullyAuthenticated
  • Prinzipal , Authentifizierung
  • hasPermission

Und lassen Sie uns nun jedes davon im Detail durchgehen.

4.1. hasRole, hasAnyRole

Diese Ausdrücke sind für die Definition der Zugriffssteuerung oder Autorisierung für bestimmte URLs oder Methoden in Ihrer Anwendung verantwortlich.

Schauen wir uns das Beispiel an:

@Override protected void configure(final HttpSecurity http) throws Exception { ... .antMatchers("/auth/admin/*").hasRole("ADMIN") .antMatchers("/auth/*").hasAnyRole("ADMIN","USER") ... } 

In diesem Beispiel geben wir den Zugriff auf alle Links an, die mit / auth / beginnen und auf Benutzer beschränkt sind, die mit der Rolle USER oder der Rolle ADMIN angemeldet sind . Um auf Links zuzugreifen, die mit / auth / admin / beginnen , benötigen wir außerdem eine ADMIN- Rolle im System.

Die gleiche Konfiguration kann in einer XML-Datei erreicht werden, indem Sie Folgendes schreiben:

4.2. hasAuthority, hasAnyAuthority

Rollen und Behörden sind im Frühjahr ähnlich.

Der Hauptunterschied besteht darin, dass Rollen eine spezielle Semantik haben. Ab Spring Security 4 wird das Präfix ' ROLE_ ' automatisch durch eine rollenbezogene Methode hinzugefügt (sofern es noch nicht vorhanden ist).

So hasAuthority ( 'ROLE_ADMIN') ähnlich ist hasRole ( 'ADMIN') , weil die ' ROLE_ ' Präfix wird automatisch hinzugefügt.

Das Gute an der Verwendung von Behörden ist jedoch, dass wir das Präfix ROLE_ überhaupt nicht verwenden müssen .

Hier ist ein kurzes Beispiel, in dem wir Benutzer mit bestimmten Berechtigungen definieren:

@Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication() .withUser("user1").password(encoder().encode("user1Pass")) .authorities("USER") .and().withUser("admin").password(encoder().encode("adminPass")) .authorities("ADMIN"); } 

Wir können dann natürlich diese Autoritätsausdrücke verwenden:

@Override protected void configure(final HttpSecurity http) throws Exception { ... .antMatchers("/auth/admin/*").hasAuthority("ADMIN") .antMatchers("/auth/*").hasAnyAuthority("ADMIN", "USER") ... }

Wie wir sehen können, erwähnen wir hier überhaupt keine Rollen. Zusätzlich benötigen wir ab Frühjahr 5 eine PasswordEncoder- Bean:

@Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); }

Schließlich können wir die gleiche Funktionalität natürlich auch mit der XML-Konfiguration erreichen:

Und:

4.3. allowAll, leugnenAll

Diese beiden Anmerkungen sind auch recht einfach. Wir können entweder den Zugriff auf eine URL in unserem Service zulassen oder den Zugriff verweigern.

Schauen wir uns das Beispiel an:

... .antMatchers("/*").permitAll() ...

Mit dieser Konfiguration autorisieren wir alle Benutzer (sowohl anonym als auch angemeldet), auf die Seite zuzugreifen, die mit '/' beginnt (z. B. unsere Homepage).

Wir können auch den Zugriff auf unseren gesamten URL-Bereich verweigern:

... .antMatchers("/*").denyAll() ...

Die gleiche Konfiguration kann auch mit einer XML-Konfiguration durchgeführt werden:

4.4. isAnonymous, isRememberMe, isAuthenticated, isFullyAuthenticated

In this subsection we focus on expressions related to login status of the user. Let's start with user that didn't log in to our page. By specifying following in Java config, we enable all unauthorized users to access our main page:

... .antMatchers("/*").anonymous() ...

The same in XML config:

If we want to secure the website that everybody who uses it will be required to login, we need to use isAuthenticated() method:

... .antMatchers("/*").authenticated() ...

or XML version:

Moreover, we have two additional expressions, isRememberMe() and isFullyAuthenticated(). Through the use of cookies, Spring enables remember-me capabilities so there is no need to log into the system each time. You can read more about Remember Me here.

In order to give the access to users that were logged in only by remember me function, we may use this:

... .antMatchers("/*").rememberMe() ...

or XML version:

Finally, some parts of our services require the user to be authenticated again even if the user is already logged in. For example, user wants to change settings or payment information; it's of course good practice to ask for manual authentication in the more sensitive areas of the system.

In order to do that, we may specify isFullyAuthenticated(), which returns true if the user is not an anonymous or a remember-me user:

... .antMatchers("/*").fullyAuthenticated() ...

or the XML version:

4.5. principal, authentication

These expressions allow accessing the principal object representing the current authorized (or anonymous) user and the current Authentication object from the SecurityContext, respectively.

We can, for example, use principal to load a user's email, avatar, or any other data that is accessible in the logged in user.

And authentication provides information about the full Authentication object, along with its granted authorities.

Both are described in further detail in the following article: Retrieve User Information in Spring Security.

4.6. hasPermission APIs

This expression is documented and intended to bridge between the expression system and Spring Security’s ACL system, allowing us to specify authorization constraints on individual domain objects, based on abstract permissions.

Let's have a look at an example. We have a service that allows cooperative writing articles, with a main editor, deciding which article proposed by other authors should be published.

In order to allow usage of such a service, we may create following methods with access control methods:

@PreAuthorize("hasPermission(#articleId, 'isEditor')") public void acceptArticle(Article article) { … }

Only authorized user can call this method, and also user needs to have permission isEditor in the service.

We also need to remember to explicitly configure a PermissionEvaluator in our application context:

Dabei ist customInterfaceImplementation die Klasse, die PermissionEvaluator implementiert .

Natürlich können wir dies auch mit der Java-Konfiguration tun:

@Override protected MethodSecurityExpressionHandler expressionHandler() { DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler(); expressionHandler.setPermissionEvaluator(new CustomInterfaceImplementation()); return expressionHandler; }

5. Schlussfolgerung

Dieses Tutorial ist eine umfassende Einführung und Anleitung zu Spring Security Expressions.

Alle hier diskutierten Beispiele sind im GitHub-Projekt verfügbar.