Learn Spring Security
Contents
Authorize Using Spring Beans
Simple authorization rules can be written using SpEL expressions inside Method security annotations. But there can be rules which are quite harder to write in SpEL, where the expression itself could be better off reside in its own method rather than as a complex String constant.
Make Instructor's profile public
Let's extend the ViewProfile usecase to make Instructor's profiles public in addition to viewing one's own profile. This can only be done by checking if the requested user profile has Instructor role something like below.
appuser.getRoles()
.stream()
.anyMatch(appRole ->
appRole.getName().equals(RoleEnum.INSTRUCTOR)
);
Is there any simpler way to implement this in SpEL expressions? Well, we can do this using Spring Beans. Let's define a Spring Bean @Component to hold a collection of helper methods which can be used to secure your Service layer.
@Component("serviceSecurity")
public class ServiceSecurity {
public Boolean isInstructor(AppUser appUser) {
appuser.getRoles()
.stream()
.anyMatch(appRole ->
appRole.getName().equals(RoleEnum.INSTRUCTOR)
);
}
}
We can call the above Bean method with the requested user profile as the argument. We can refer the Bean component using it's name prefixed with @ [@serviceSecurity] and we can access the requested user profile from returnObject inside @PostAuthorize(). We should combine it with the existing condition with an or condition like below.
@PreAuthorize(Authority.VIEW_PROFILE)
@PostAuthorize("@serviceSecurity.isInstructor(returnObject) or returnObject.username == authentication.name")
public AppUser get(Long userId) {
...
}
Let's send the last unauthorized request again to view Gru's user profile using Bob's credential. We can view the Instructor's profile this time.