6

I am using loadUserByUsername method to authenticate user, however, I need to validate against allowed ip addresses as well.

But when I am trying

SecurityContextHolder.getContext().getAuthentication(); 

getting null.

Please advice, how I can access users client ip address while authenticating user.

user3364699
  • 155
  • 1
  • 2
  • 12
  • Why do you need the ip-address while authentication. Why not simply use expressions to check if the ip-address has access. – M. Deinum Mar 04 '14 at 12:12
  • @Deinum, the allowed ip address will be assigned to user accounts, not fixed ip addresses, so I cant use with expressions. – user3364699 Mar 04 '14 at 12:40
  • And why wouldn't you be able to use expressions? The `UserDetailsService` is only for loading the user. If this is your custom user you can write an expression to see if the current IP address is in the list of allowed ip-adresses. I still don't see why you wouldn't be able to use expressions. However the first step is to solve it in the right place and the `UserDetailsService` isn't the right place. – M. Deinum Mar 04 '14 at 13:02
  • I used the similar approach mentioned in the url http://stackoverflow.com/questions/10147161/authenticating-by-ip-address-in-spring-3-1-smartest-way-to-do-that and worked – user3364699 Mar 04 '14 at 16:02

3 Answers3

7

To solve your problem you should implement custom authentication provider (that can be based on DaoAuthenticationProvider or can be implemented from scratch, etc). This authentication provider should be registered in Authentication manager providers set. Also, this provider will have autowired HttpServletRequest type property, related to context http request. Then, when you performing client authenticationv via that provider, you can obtain user IP address by invoking HttpServletRequest.getRemoteAddr(). Code:

/**
 * IP address based authentication provider
 */
@Service 
public class IPAddressBasedAuthenticationProvider extends AuthenticationProvider {

     /**
      * Context http request
      */
     @Autowired
     private HttpServletRequest request;

     @Override
     public Authentication authenticate(Authentication authentication) throws AuthenticationException {

         String ipAddress = request.getRemoteAddr();
         //do authentication specific stuff (accessing users table in database, etc.)
         //return created authentication object (if user provided valid credentials)
    }
}

Configuration:

<security:http auto-config="true" authentication-manager-ref="authenticationManager" use-expressions="true"/>

<bean id="authenticationManager" class="org.springframework.security.authentication.ProviderManager">
 <constructor-arg name="providers">
  <list>
   <ref bean="iPAddressBasedAuthenticationProvider"/>
  </list>
 </constructor-arg>
</bean>

Also, you can add other authentication providers (if you need to). Hope this helps. Links: AuthenticationProvider ProviderManager

nndru
  • 2,057
  • 21
  • 16
  • I used similar approach mentioned in the url http://stackoverflow.com/questions/10147161/authenticating-by-ip-address-in-spring-3-1-smartest-way-to-do-that – user3364699 Mar 04 '14 at 16:00
  • If you already have performed authentication by 'UserDetailsService' you can add extra 'AuthenticationManager' which will hold http request and obtain valid 'Authentication' object, where you can perform what do you actually need. Or you can extend 'UserDetailsService' with http request. So, main point is to create service that will hold http request from one side and authentication data from other. – nndru Mar 04 '14 at 20:10
  • yet it quite old post, one more notice: this won't work unless you have listener org.springframework.web.context.request.RequestContextListener registered. – andrew.dman Jun 05 '17 at 12:17
  • For sure, if you'd like to use 'request'-scoped stuff you should apply particular listener. – nndru Jun 10 '17 at 10:49
5
/**
 * IP address based authentication provider
 */
@Service 
public class IPAddressBasedAuthenticationProvider extends AuthenticationProvider {

     @Override
     public Authentication authenticate(Authentication authentication) throws AuthenticationException {

              final WebAuthenticationDetails details = (WebAuthenticationDetails) auth.getDetails();
              details.getRemoteAddress();
    }
}
makson
  • 1,975
  • 3
  • 23
  • 31
2

You are implementing UserDetailsService's loadUserByUsername method.

As per documentation There is often some confusion about UserDetailsService. It is purely a DAO for user data and performs no other function other than to supply that data to other components within the framework. In particular, it does not authenticate the user, which is done by the AuthenticationManager. In many cases it makes more sense to implement AuthenticationProvider directly if you require a custom authentication process.

UserDetails userDetails= customUserDetailsService.loadUserByUsername("name"); 

this will give a userDetails object.You can do all authority related code in loadUserByUsername().If you would like to manually set an authenticated user in Spring Security.follow the code

 Authentication authentication= new  UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()) ;  
                SecurityContextHolder.getContext().setAuthentication(authentication);

You will get IP address from request header.

How can I retrieve IP address from HTTP header in Java

you can do that somewhere in spring security filterchain.

Community
  • 1
  • 1
RPaul
  • 946
  • 10
  • 11