Introduktion till vårens säkerhetsuttryck

1. Introduktion

I denna handledning fokuserar vi på Spring Security Expressions, och naturligtvis på praktiska exempel med dessa uttryck.

Innan du tittar på mer komplexa implementeringar (som ACL) är det viktigt att ha ett gott grepp om säkerhetsuttryck - eftersom de kan vara ganska flexibla och kraftfulla om de används korrekt.

Den här artikeln är en förlängning av Spring Security Expressions - hasRole Exempel.

2. Maven Beroenden

För att kunna använda Spring Security måste du inkludera följande avsnitt i din pom.xml- fil:

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

Senaste versionen finns här.

Och en snabb anmärkning - detta beroende täcker bara vårsäkerhet; glöm inte att lägga till s pring-core och spring-context för en fullständig webbapplikation.

3. Konfiguration

Låt oss först titta på en Java-konfiguration.

Vi utökar WebSecurityConfigurerAdapter - så att vi har möjlighet att ansluta till någon av de förlängningspunkter som basklassen erbjuder:

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

Vi kan naturligtvis också göra en XML-konfiguration:

4. Webbsäkerhetsuttryck

Låt oss börja titta på säkerhetsuttrycken:

  • hasRole , hasAnyRole
  • hasAuthority , hasAnyAuthority
  • permitAll , denyAll
  • isAnonymous , isRememberMe , isAuthenticated , isFullyAuthenticated
  • princip , autentisering
  • hasPermission

Och låt oss nu gå igenom vart och ett av dessa i detalj.

4.1. hasRole, hasAnyRole

Dessa uttryck är ansvariga för att definiera åtkomstkontroll eller auktorisering till specifika webbadresser eller metoder i din applikation.

Låt oss titta på exemplet:

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

I det här exemplet anger vi åtkomst till alla länkar som börjar med / auth / begränsad till användare som är inloggade med rollen USER eller roll ADMIN. Dessutom måste vi ha ADMIN- roll i systemet för att komma åt länkar som börjar med / auth / admin / .

Samma konfiguration kan uppnås i XML-fil genom att skriva:

4.2. hasAuthority, hasAnyAuthority

Roller och myndigheter liknar våren.

Huvudskillnaden är att roller har speciell semantik - från och med Spring Security 4 läggs prefixet ' ROLE_ ' automatiskt till (om det inte redan finns) med någon rollrelaterad metod.

hasAuthority ('ROLE_ADMIN') liknar hasRole ('ADMIN') eftersom prefixet ' ROLE_ ' läggs till automatiskt.

Men det bra med att använda myndigheter är att vi inte alls behöver använda prefixet ROLE_ .

Här är ett snabbt exempel där vi definierar användare med specifika myndigheter:

@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"); } 

Vi kan naturligtvis sedan använda dessa myndighetsuttryck:

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

Som vi kan se nämner vi inte roller alls här. Dessutom, från och med våren 5, behöver vi en PasswordEncoder- böna:

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

Slutligen - vi kan naturligtvis uppnå samma funktionalitet med XML-konfiguration också:

Och:

4.3. permitAll, denyAll

Dessa två anteckningar är också ganska enkla. Vi kan antingen tillåta åtkomst till någon URL i vår tjänst eller så kan vi neka åtkomst.

Låt oss ta en titt på exemplet:

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

Med den här konfigurationen tillåter vi alla användare (både anonyma och inloggade) att komma åt sidan som börjar med '/' (till exempel vår hemsida).

Vi kan också neka åtkomst till hela webbadressutrymmet:

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

Och igen, samma konfiguration kan också göras med en XML-konfiguration:

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:

där customInterfaceImplementation är den klass som implementerar PermissionEvaluator.

Naturligtvis kan vi också göra detta med Java-konfiguration:

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

5. Sammanfattning

Denna handledning är en omfattande introduktion och guide till Spring Security Expressions.

Alla exempel som diskuteras här är tillgängliga i GitHub-projektet.