0

In my web-application I'm using Spring Security and UserDetailsService implementation for authentication.

Now I neet to get and store somewhere the client IP address for the current session and I'd like to store it in UserDetails instance to retrieve it where I need.

Which is the correct way to achieve this? Is there any facility in Spring MVC/Security to get IP address in service layer?

NOTE I also need to know IP address if the client is not authenticated (to log access attempt)

davioooh
  • 23,742
  • 39
  • 159
  • 250

1 Answers1

4

The ip-address is already present in the Authentication object (not the UserDetails).

You can call getDetails() on the Authentication object and in a web application and properly configured Spring Security environment this will give you an instance of WebAuthenticationDetails which has the ip-address inside it. You can call the getRemoteAddress method to obtain the address. (See the javadoc)..

Authentication auth = SecurityContextHolder.getContext().getAuthentication();
WebAuthenticationDetails details = (WebAuthenticationDetails) auth.getDetails();
String ipAddress = details.getRemoteAddress();

Something along those lines, you could put this behind a utility method or something to obtain the ip-address.

Apparently you want to log authentication attempts, this can be easily achieved by implementing an ApplicationListener and let that listen to AbstractAuthenticationEvents. Spring Security issues those for each authentication attempt, and also includes the Authentication (containing the IP-address) into it.

public class AuthenticationAttemptLoggerListener implements ApplicationListener<AbstractAuthenticationEvent> {

    private final Logger logger = LoggerFactory.getLogger(AuthenticationAttemptLoggerListener.class);

    public void onApplicationEvent(AbstractAuthenticationEvent event) {
        Authentication auth = event.getAuthentication();
        WebAuthenticationDetails details = (WebAuthenticationDetails) auth.getDetails();
        String ipAddress = details.getRemoteAddress();

        if (event instanceof AbstractAuthenticationFailureEvent) {
            logger.warn("Unsuccesful authentication attemped from: {}", ipAddress);
        } else {
            logger.info("Succesful authentication attemped from: {}", ipAddress);
        }
    }
}

Something like this should catch and log everything. You might want to take a look at all the available events.

homaxto
  • 5,428
  • 8
  • 37
  • 53
M. Deinum
  • 115,695
  • 22
  • 220
  • 224
  • I also need to know IP address if the client is not authenticated (to log access attempt) – davioooh Apr 10 '14 at 12:59
  • The details should always be set, those are set before the authentication is actually happening (check the sources of the `UsernamePasswordAuthenticationFilter`. If you want to log attempts simply create an `ApplicationListener` that listens for `AbstractAuthenticationFailureEvent` or if you want all events `AbstractAuthenticationEvent` and then simply retrieve it from the `Authentication` object. – M. Deinum Apr 11 '14 at 06:04