Authorizing methods

For a security framework to be of value, it needs flexibility. Security rules are never confined to simple use cases. We have all dealt with customers needing very complex settings for certain operations. Spring Security makes this possible through its special dialect of SpEL or Spring Expression Language.

To get a taste of it, let's augment the images microservice's ImageService.delete() method with an authorization rule:

    @PreAuthorize("hasRole('ADMIN') or " + 
     "@imageRepository.findByName(#filename).owner " + 
      "== authentication.name") 
    public Mono<Void> deleteImage(String filename) { 
 
      ... rest of the method unchanged ... 
    } 

This preceding code for deleting images is only different in the new annotation in the following manner:

  • The method is flagged with a @PreAuthorize annotation, indicating that the SpEL expression must evaluate to true in order for the method to get called
  • hasRole('ADMIN') indicates that a user with ROLE_ADMIN is allowed access
  • or @imageRepository.findByName(#filename).owner == authentication.name") indicates that access is also granted if the user's name matches the image's owner property
Why do we need this authorization rule again? Because without it, any authenticated user can delete any image. Probably not a good idea.

This authorization rule is just one example of the types of rules we can write. The following table lists the prebuilt rules provided by Spring Security:

SpEL function

Description

hasAuthority('ROLE_USER')

Access is granted if user has ROLE_USER

hasAnyAuthority('ROLE_USER', 'ROLE_ADMIN')

Access is granted if user has any of the listed authorities

hasRole('USER')

Shorthand for hasAuthority('ROLE_USER')

hasAnyRole('USER', 'ADMIN')

Shorthand for hasAnyAuthority('ROLE_USER', 'ROLE_ADMIN')

principal

Direct access to the Principal object representing the user

authentication

Direct access to the Authentication object obtained from the security context

permitAll

Evaluates to true

denyAll

Evaluates to false

isAnonymous()

Returns true if user is an anonymous user

isRememberMe()

Returns true if user is a remember-me user

isAuthenticated()

Returns true if user is not anonymous

isFullyAuthenticated()

Returns true if user is neither anonymous nor a remember-me user

 

It's possible to combine these SpEL functions with and and or.

As we saw demonstrated earlier, we can also write security checks like this:

    @PreAuthorize("#contact.name == authentication.name") 
    public void doSomething(Contact contact); 

This preceding security check will grab the method's contact argument and compare its name field against the current authentication object's name field, looking for a match.

By the way, these types of parameter-specific rules are great when we want to restrict operations to the owner of the record, a common use case. In essence, if you are logged in and operating on your data, then you can do something.

In addition to all these functions and comparators, we can also invoke beans (another thing shown earlier). Look at the following code, for example:

    @PreAuthorize("@imageRepository.findByName(#filename).owner ==
authentication.name")

This last security check will invoke the bean named imageRepository  and use its findByName function to look up an image's owner and then compare it against the current authentication object.

@PreAuthorize rules can be applied to any Spring bean, but it's recommended you apply them to your service layer methods. In essence, any code that invokes the service layer, whether it was from a web call or somewhere else, should be secured. Wrapping higher up at the web handler can leave your service layer susceptible to unauthorized access. To guard against improper web calls, it's recommended that you use route-based rules (as shown earlier in the chat microservice's SecurityConfiguration policy).
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.189.170.134