OK, took me a bit longer to get to this post that I wanted. I am also going to make this public before it is 100% complete. So stay tuned I might be updating this with more information as time goes by.
In Part 1 on this Spring Security series I talked about the goals of Spring Security and started covering the design of the Authentication pieces of Spring Security. In Part 2 we will talk about the design of the Authorization pieces of Spring Security. In Part 3 we will talk about setting up Spring Security and the basic configuration that you need to do to secure Web URLs and Method security.
So Authorization is a bit more complex because there are many decisions to be made about the granularity of your security authorization. Meaning are secured resources going to be accessible to members of a GROUP, high coarse grained authorization. Or ROLE based which is a little bit less coarse, but still easy to maintain users to roles, just like groups. Or you could be more fine grained using ACLs, permissions that determine what a user can do. Or even more fine grained down to specific rows of data that a user can see.
And Spring Security needs to be able to provide all those granularities while still having a simple consistent, extensible, flexible approach. Now that is a tough thing to do, but I think that Spring Security did an exceptional job at it.
So, for a high level talk about the components and design of authorization in Spring Security, we are only going to look at one simple solution (Yes, I am taking the easy way out). In our article today, we will take the ROLE based approach to authorization. Where we say a user must be a member of ROLE_USER or ROLE_ADMIN in order to see the Account edit page on a website. Or maybe to call a particular method.
So after we have been authenticated and we want to access some secured resource. Say a URL, or a method we need something to check to see if the current user has some groups, role, or permission that is needed for that resource. Typically it is easy to do Role based decisions here. So we have information of what role you need to access the resource as well as the current users roles (Stored in their UserDetails, which talked about in the last article)
So now we need someone to compare the two. So the incoming Thread call is intercepted and the information is passed to an object calls an AccessDecisionManager. OH BOY! Another Manager. Just what we always needed. Someone who does nothing but delegate. And does it delegate. It delegates to a Collection of objects called AccessDecisionVoter(s). A Voter is nothing more than a method in the AccessDecisionVoter interface that returns an int. Yay (positive number), Nay(negative number) or Abstain(0 is returned). So it the responsibility of a Voter to vote on whether the user should have access to the resource. We should say there are a couple of supports() methods that tell the AccessDecisionManager what types of decisions they support and should be called upon. (Basically, not all voters vote. If a Group is passed in for the check, why should a Role Based voter even vote.)
For something like Role Based security, the Voter is given the resource settings as well as the current Thread’s User and compares the Roles the user has against what is needed for the resource. If they have a match, then great Yay is voted. The Voter returns a positive integer. If they want to vote No, then they return a negative number.
As a matter of fact in basic environments of Spring Security with things like
OK, anyway. You have these voters voting on whether to allow the user through to the resource. Here is where things get fun. You can have a whole collection of Voters, each voting. So we might have a count of how many returned positive YAY numbers and set it such that all of the voters have to say YAY or you don’t get though. Or make it a majority (Not sure what happens if you have an even number of Voters), or just one needs to say YAY to let you through.
Pretty cool. I have found about 8 different voter implementation in Spring Security. But you could also write your own.