Spring Security is great for doing role-based authorization, but it seems to fall short when it comes to rule-based authorization. Sure, there are ways to do it via SpEL, but going that route seems to lock your authorization logic inside the annotations when it would be much better to pull that logic out into a service so that multiple places can use the same logic.
There seem to be some ways to go about adding in your own SpEL expressions, but noting is particularly clear, and even those that make sense to me seem to fall short. I would think, given how flexible Groovy is, that there must be some way to not have to hard-code the dependencies together, but to have the security rules (or SpEL extensions) picked up at run-time.
While not ideal, even something as seemingly simple as defining all of the desired new rules and injecting the as mixins (ie. SecurityExpressionRoot.mixin MyRule1
) would be a good start, but that doesn't seem to work.
Does anyone know of an example that does this? If not, how might I go about doing this myself?
One (simplified) example : A user can only take a particular action (ie. execute a service method) with an object if 3 of 4 fields have values over a particular threshold, but only if the object is less than 3 days old:
class MyRule {
boolean canTakeAction(Person person, MyThing myThing) {
int numFieldsWithValues = 0
if (myThing.field1 != null) { numFieldsWithValues++ }
if (myThing.field2 != null) { numFieldsWithValues++ }
if (myThing.field3 != null) { numFieldsWithValues++ }
if (myThing.field4 != null) { numFieldsWithValues++ }
return (numFieldsWithValues > 3) && (ageInDays(myThing) < 3)
}
int ageInDays(MyThing myThing) {
...
}
}
And that is one of the simpler rules.