May 6th, 2010, 09:11 AM
Add roles based on IP
I have a requirement to limit sign-in to only those with a certain IP range. After sign-in, if the user does not belong to a certain IP range they need to be shown a page which notifies them that a subscription is required, this is a different page to when a user types their username or password wrong.
Currently I have an AuthenticationSuccessHandler which signs the user out and shows a subscription info page if they do not have ROLE_SUBSCRIBER in their granted authorities. But I can't figure out how to add ROLE_SUBSCRIBER to a signed in (or signing in) user's Authentication.
When a user signs in, the only way to assign granted authorities (that I know of) is in UserDetailsService.loadUserByUsername(String username). However this method obviously doesn't give me access to the IP address the request originated from (usually pulled from ServletRequest.getRemoteAddr()). This IP address is required to determine if the user is accessing the site from inside a subscription zone.
I've had a look at two different approaches to doing this:
The first was to create an authentication success handler that adds ROLE_SUBSCRIBER to the authentication by proxying the original authentication. Calls to getGrantedAuthorities() returned the original assigned roles (ROLE_USER etc) plus the addition of ROLE_SUBSCRIBER. The problem with this approach is that one of the arguments of AuthenticationSuccessHandler.onAuthenticationSucce ss() is the Authentication object itself. The proxying method doesn't work as the authentication is passed by reference and hence can't be replaced. Setting the Authentication in the SecurityContext manually doesn't work either as it is overridden after the AuthenticationSuccessHandler is called.
A possible solution, which I'm yet to attempt, is to create a filter that runs before authentication and adds the user's IP address to ThreadLocal. When the call to UserDetailsService.loadUserByUsername(String username) is made, the IP address can then be pull out of ThreadLocal and used to determine if the user is signing in from an IP address within a subscription range.
Can anyone suggest a cleaner way of implementing the assignment of roles based on an IP address for a signing in user.
Thanks in advance,
Last edited by rapaul; May 6th, 2010 at 09:15 AM.
Reason: ROLE_SUBSCRIBER instead of SUBSCRIPTION
May 6th, 2010, 09:15 AM
Implement AuthenticationProvider directly, rather than UserDetailsService. Then you can access the IP address via the Authentication.details property (which should normally be an instance of WebAuthenticationDetails).
Last edited by Luke Taylor; May 6th, 2010 at 09:21 AM.
May 6th, 2010, 09:17 AM
Thanks for the prompt reply Luke. I'll give it a crack, if you don't hear back from me then you've solved my problem
Tags for this Thread